[!TIP] 本页解剖
dotnet new bitzorcas-host模板矩阵的生成结果。从零建新工程优先考虑 bitz 脚手架;两通道以同一已验证消费者工程为契约基线。
模板输出是一份客户拥有的 Solution 加商业包消费闭包。本文以 default-business-multi + sqlsugar 生成的 Acme.ServiceDesk 为主例,并标出 Mini、Single 与扩展 Profile 的差异。
所有权边界
客户可以修改 Host 与 Starter Module,但必须继续遵守生成的架构测试。Framework、Platform、Workflow、Licensing 和 Generator 以 NuGet 包进入,不应复制源码后本地分叉。
Multi Business 目录
Acme.ServiceDesk/├── Acme.ServiceDesk.slnx├── Directory.Build.props├── Directory.Build.targets├── Directory.Packages.props├── NuGet.Config├── README.md├── composition-manifest.json├── composition-manifest.schema.json├── composition-plan.json├── src/│ ├── Hosts/│ │ ├── Acme.ServiceDesk.Api/│ │ │ ├── Authentication/│ │ │ ├── Composition/│ │ │ ├── Configuration/│ │ │ ├── Schema/│ │ │ ├── Tenancy/│ │ │ ├── Program.cs│ │ │ └── appsettings*.json│ │ ├── Acme.ServiceDesk.AppHost/│ │ └── Acme.ServiceDesk.ServiceDefaults/│ └── Modules/Business/Starter/│ ├── Acme.ServiceDesk.Modules.Business.Starter.Contracts/│ └── Acme.ServiceDesk.Modules.Business.Starter.Application/└── tests/ ├── Acme.ServiceDesk.Unit.Tests/ └── Acme.ServiceDesk.Architecture.Tests/输出没有 JobHost、前端项目、部署 YAML、维护脚本或底座产品源码。某个文件未生成,先核对 Profile 合同,不要假设生成中断。
三种基础输出差异
| 项目/能力 | Mini API Single | Default Business Single | Default Business Multi |
|---|---|---|---|
| API | ✓ | ✓ | ✓ |
| ServiceDefaults | ✓ | ✓ | ✓ |
| Unit / Architecture Tests | ✓ | ✓ | ✓ |
| Business Starter Contracts/Application | — | ✓ | ✓ |
| AppHost | — | — | ✓ |
| Tenancy contract | fixed tenant context | fixed tenant context | authenticated tenant_id claim |
| Deployment | none | none | aspire |
| SQL Server 开发编排 | — | — | AppHost |
Mini Development Shell 可不连接 SQL Server 运行;Business Profile 需要真实数据库合同。Single Profile 由部署 Runbook 提供连接串并执行 Schema,Multi Profile 由 AppHost 在开发环境编排。
API Host 是组合根
Program.cs 负责:
- 配置失败关闭校验;
- ServiceDefaults、Problem Details、Forwarded Headers 与 OpenAPI;
- CurrentTenant、CurrentUser 和 Persistence execution context;
- 编译期生成的 Module、Endpoint 与 ORM Adapter 注册;
- Mediator pipeline、License、JWT 与 Authorization;
- Health、Tenant middleware 与 Endpoint 映射;
- Schema 或平台运维命令的进程入口。
业务规则不应进入 Host。Host 只组合客户模块和商业包:
rg -n 'AddBitzOrcas|MapBitzOrcas|MapAllGeneratedEndpoints|UseBitzOrcasModules' \ src/Hosts/Acme.ServiceDesk.Api/Program.csSqlSugar 与 EF Core 输出的 Program.cs 不同;选中 Provider 的注册是物理代码,不是运行时读取 manifest 后决定。API 与 AppHost 两条接线的真实 rg 命中:
AppHost 的顺序保证
Multi 输出中的 AppHost:
- 创建 SQL Server 与
PrimaryDatabase; - 创建一次性 API 项目资源
schema-migrator; - 传入
--migrate-schema apply并等待数据库; - 启动常驻 API,注入数据库与 Persistence identity;
- 用
WaitForCompletion(schemaMigrator)阻止迁移失败后的 API 启动。
rg -n 'AddSqlServer|AddDatabase|schema-migrator|WaitForCompletion' \ src/Hosts/Acme.ServiceDesk.AppHost/Program.csAuthorization Multi Profile 还增加 RabbitMQ 与 authorization-bootstrap。其他 Multi Profile 不应出现这些资源。
Business Starter 是完整垂直切片
Contracts 项目中的 WorkItem 是统一聚合根和持久化事实模型:
- 继承
TenantAggregateRoot<string>; [BitzTable]声明租户与软删除;[BitzColumn]定义标题约束;- 公开无参构造仅供 ORM 物化,业务创建只能走
Create; - 标题空白、超过 160 字符或租户无效时返回稳定错误。
Application 项目中的 CreateWorkItemCommand:
- 用
[GenerateEndpoint]生成POST /api/work-items; - 实现
IAuthorizedRequest,声明资源与 Create 动作; - Handler 从可信
ICurrentTenant获取租户; - 直接使用
ICommandRepository<WorkItem,string>保存聚合; - 事务、DI、Endpoint 和 ORM Adapter 由生成式管线接线。
rg -n 'BitzTable|TenantAggregateRoot|GenerateEndpoint|ICommandRepository' \ src/Modules/Business/Starter不要为同一事实再创建 Entity、Mapper、MappingSpec、DataPort 或 Infrastructure 项目。这会破坏统一聚合路径,并被架构门禁识别。
商业包与中央版本
Directory.Packages.props 统一管理商业包版本,NuGet.Config 固定 Feed source mapping。API 通过 Profile 包获取基线闭包:
| 输出 | Profile 包 | ORM 包 |
|---|---|---|
| Mini | BitzOrcas.Profile.Mini.Api | SqlSugar 或 EF Core 对应 Infrastructure |
| Business | BitzOrcas.Profile.Default.Business | SqlSugar 或 EF Core 对应 Infrastructure |
Business Starter Contracts 只依赖 Domain、Persistence Metadata 与 Generator;Application 依赖 Application、Modularity 以及条件性 Industry 包。项目引用方向保持 Host → Application → Contracts。
composition-manifest.json
Manifest 是最终组合事实,当前 schemaVersion=2。主要字段:
| 字段 | 用途 |
|---|---|
profileChoice/profileId/profilePackageId | 公开选择与商业 Profile |
runtimeAdapter | 实际 ORM |
tenancy/deployment | 请求隔离与运行拓扑 |
platformModule/industryExtension | 条件闭包 |
hosts/projects | 物理 Solution 成员 |
modules/capabilities | Module、Endpoint、Job、租户合同 |
packages/packageReferences/projectReferences | 依赖闭包和方向 |
generators/endpointAssemblies/jobAssemblies | 编译期发现面 |
licenseFeatures | Runtime License 需求 |
verification | 生成版本建议的验证命令 |
excluded | 明确未选择的能力 |
# 先确认 Schema、Profile 与 ORM 版本字段。# 再审阅运行成员、License 需求和明确排除项。jq '{ schemaVersion, profileChoice, runtimeAdapter, hosts, modules, capabilities, licenseFeatures, excluded}' composition-manifest.jsonManifest 不读取运行时状态,也不证明 Feed Token、License、数据库或业务配置有效。
composition-plan.json
Plan 是物理输出清单,当前 schemaVersion=1:
selectedProjects:应进入 Solution 的项目;selectedEndpoints/selectedJobs:该 Profile 声明的入口;writeFiles:原生模板应写入的文件;removePaths:当前分支需要删除的路径。
# selected 字段描述生成选择,writeFileCount 描述物理写入面。# removePaths 应与当前 Profile 的条件裁剪一致。jq '{ schemaVersion, selectedProjects, selectedEndpoints, selectedJobs, writeFileCount: (.writeFiles | length), removePaths}' composition-plan.jsonPlan 不是重新执行脚本的输入。修改 Plan 不会增加项目、包或 Endpoint;需要另一组合时,从精确模板版本重新生成到空目录。
Platform Profile 的增量
Authorization 输出会增加:
BitzOrcas.Platform.Authorization及对应 Provider/CAP 接线;platform.authorizationLicense feature;- Authorization schema/operations command;
- Platform adoption tests;
- Multi AppHost 的 RabbitMQ、Schema 后 bootstrap 和独立操作身份。
MasterData 输出增加 MasterData 运行时包、Provider、License feature 与采用测试,但不会增加 Authorization 的 RabbitMQ/bootstrap 文件。
这些实现仍来自商业包;Consumer 只拥有 Host 接线和采用证据。
Industry Profile 的增量
Finance、HR、Auction、Legal Profile 在 Starter Application 中增加对应行业扩展包和能力标识,并保留 IndustryExtensionAdoptionTests。行业扩展不会生成新的行业业务模块源码;客户需要基于包合同建立自己的 Owner Module。
检查最终闭包时以 manifest 为准,因为 Auction 或 Legal 可能因依赖关系同时包含 Finance 包。
测试项目
Unit Tests 检查 Result、License composition、Profile/ORM、Schema、Starter Aggregate 和条件扩展采用。Architecture Tests 检查:
- Consumer 不复制 Framework/Platform 源码;
- Application 不依赖 ORM/Host;
- 聚合不变量留在聚合;
- Owner private 类型不泄漏到公开合同;
- Handler 与 Endpoint 保持切片本地;
- Module/Host 项目引用与生成式接线符合边界。
dotnet test tests/Acme.ServiceDesk.Architecture.Tests \ --configuration Release这些测试是客户仓库后续修改的持续门禁,不是只在生成当天运行一次。
扩展位置
| 需求 | 应修改/新增的位置 | 不应修改的位置 |
|---|---|---|
| 新业务不变量 | Owner Module 的 Aggregate | API Program.cs |
| 新用例 | 同一 Module 的 Command/Query + Handler | 通用 Framework |
| 新 Endpoint | 用例上的生成属性 | 手写全局路由注册 |
| 新持久化字段 | 统一聚合元数据 + Schema | 平行 Entity/Mapper |
| 采用 Platform/Industry | Host 接线、Owner 合同与测试 | 手改 manifest 假装已采用 |
| 升级商业包 | 中央版本 + 锁文件 +升级证据 | 复制商业包源码 |