Skip to content
bitzorcas
中EN

Guide

解决方案模板故障排查

按安装、生成、Feed、Restore、Build、Schema、运行拓扑、平台模块与 License 阶段诊断 bitzorcas-host。

Last updated

[!TIP] 本页排查 dotnet new bitzorcas-host 模板矩阵。bitz 脚手架的故障排查见 bitz 交互式脚手架的已知限制与退出码章节。

当前 bitzorcas-host 是原生 dotnet new 模板。先定位失败阶段,再查看该阶段的输入和证据;不要把后续数据库或许可证问题归因于“模板没有生成”。

快速定位

否是否是否是否是否是否

模板 Help 是否正确

安装版本/缓存

空目录生成是否成功

Profile、ORM、文件冲突

Manifest 与文件是否一致

陈旧模板/手工修改/非空目录

Restore 是否成功

Feed、凭据、entitlement、锁文件

Build/Test 是否成功

SDK、包闭包、ORM、架构门禁

Schema/Host 是否启动

数据库、Persistence、JWT、Platform、License

先采集最小上下文:

Terminal window
# 只采集版本、模板注册和源键;不要输出凭据环境变量。
dotnet --info
dotnet new list bitzorcas-host
dotnet new bitzorcas-host --help
dotnet nuget list source

Help 没有模板或参数不对

找不到 bitzorcas-host

Terminal window
dotnet new install BitzOrcas.Modern.Templates@1.0.0-alpha1
dotnet new list bitzorcas-host

安装失败先解决 Feed。模板包与生成后商业依赖都来自授权 Feed,能访问 nuget.org 不代表能安装该包。

Help 与文档不同

卸载所有本机同 ID 版本,再安装精确版本:

Terminal window
dotnet new uninstall BitzOrcas.Modern.Templates
dotnet new install BitzOrcas.Modern.Templates@1.0.0-alpha1
dotnet new bitzorcas-host --help

Help 只应公开 ProfileChoice 与 RuntimeAdapter 两个 BitzOrcas 选择器。出现旧的拆分式业务选择器或内部 generated symbol,说明安装版本/包通道与本文不一致。

ProfileChoice 或 RuntimeAdapter 被拒绝

dotnet new 会在写入前校验 choice。当前 ORM 只有:

  • sqlsugar
  • efcore

Profile 必须是参数参考列出的 15 个值之一。不要从基础词、租户词和扩展词自行拼接新值。

Terminal window
dotnet new bitzorcas-host -n Probe -o ./Probe \
--ProfileChoice default-business-single \
--RuntimeAdapter sqlsugar

choice 校验在写入任何文件之前完成。真实的拒绝效果——非法取值、模板引擎列出全部合法值、退出码 127、零写入:

bitzorcas-host session
$ 
错误: 无效选项:
--ProfileChoice no-such-profile
“no-such-profile”不是“--ProfileChoice”的有效值。 可能的值为:
default-business-multi - Business Starter、多租户、Aspire 编排;不附加行业扩展。
default-business-multi-auction - Business Starter、多租户、Aspire 编排、Auction 扩展。
default-business-multi-authorization - Business Starter、多租户、Aspire 编排、Authorization runtime module。
default-business-multi-finance - Business Starter、多租户、Aspire 编排、Finance 扩展。
default-business-multi-hr - Business Starter、多租户、Aspire 编排、HR 扩展。
default-business-multi-legal - Business Starter、多租户、Aspire 编排、Legal 扩展。
default-business-multi-masterdata - Business Starter、多租户、Aspire 编排、MasterData runtime module。
default-business-single - Business Starter、单租户、独立部署;不附加行业扩展。
default-business-single-auction - Business Starter、单租户、Auction 扩展。
default-business-single-authorization - Business Starter、单租户、Authorization runtime module。
default-business-single-finance - Business Starter、单租户、Finance 扩展。
default-business-single-hr - Business Starter、单租户、HR 扩展。
default-business-single-legal - Business Starter、单租户、Legal 扩展。
default-business-single-masterdata - Business Starter、单租户、MasterData runtime module。
mini-api-single - 最小 API、单租户、独立部署、无行业扩展。
有关详细信息,请运行:
dotnet new bitzorcas-host -h
有关退出代码的详细信息,请参阅 https://aka.ms/templating-exit-codes#127
$ echo $?
127
$ ls Probe
ls: Probe: No such file or directory

如果上述基线命令失败,保留完整错误与 Help;不要通过修改模板缓存的 template.json 继续。

输出目录冲突或不完整

模板面向新目录。已有同名文件会触发冲突;强制覆盖可能留下旧项目和新文件混合的树。

Terminal window
# 使用系统临时目录,排除既有文件和仓库配置干扰。
tmp_dir="$(mktemp -d)"
dotnet new bitzorcas-host -n TemplateProbe -o "$tmp_dir/TemplateProbe" \
--ProfileChoice default-business-multi \
--RuntimeAdapter sqlsugar

有效输出根至少有:

Terminal window
# 检查所有 Profile 都应具备的 Solution 与组合制品。
root="$tmp_dir/TemplateProbe"
test -f "$root/TemplateProbe.slnx"
test -f "$root/composition-manifest.json"
test -f "$root/composition-manifest.schema.json"
test -f "$root/composition-plan.json"
# Multi Profile 还必须具备 API 与 Architecture Tests 项目。
test -d "$root/src/Hosts/TemplateProbe.Api"
test -d "$root/tests/TemplateProbe.Architecture.Tests"

Mini 没有 Starter Module/AppHost;Single Business 没有 AppHost;Multi Business 才有二者。当前公开模板没有 JobHost 或前端项目。

Manifest 与物理树不一致

先比较 manifest 和 plan:

Terminal window
# 先比较逻辑闭包,再列出实际项目文件。
jq '{profileChoice, runtimeAdapter, hosts, projects}' \
composition-manifest.json
jq '{selectedProjects, selectedEndpoints, selectedJobs}' \
composition-plan.json
find src tests -name '*.csproj' -print | sort

常见原因:

  • 在非空目录生成,旧文件未被模板管理;
  • 生成后手工移动/删除项目;
  • 本机安装的是旧模板,文档与安装包版本不同;
  • 使用强制覆盖,导致客户文件和原生输出混合;
  • 未审阅 Git 合并冲突。

恢复方法是在新空目录用同一名称、Profile、ORM 和精确版本重新生成,再用 Git/diff 迁移客户改动。不要手改 manifest/plan 让它们“匹配”错误的树。

Feed 与 Restore

先检查源键和 URL 是否存在,不输出凭据值:

Terminal window
dotnet nuget list source
test -n "$BITZORCAS_COMMERCIAL_FEED_URL"
dotnet restore <Name>.slnx --no-http-cache --verbosity normal
现象优先判断处理
BITZFEED001Feed URL 未注入设置 BITZORCAS_COMMERCIAL_FEED_URL
401/403、认证型 NU1301Credential Provider/Token核对源键大小写、到期、撤销和 CI Secret
NU1101/NU1102entitlement/版本通道核对包 ID、1.0.0-alpha1 通道与组织授权
NU3000包签名策略修复证书链、可信根或时间;禁止关闭验证
超时/DNS/TLS网络路径检查代理、DNS、企业证书与 Feed 服务

日志可记录源键、包 ID、版本和 HTTP 状态,不能打印 NuGetPackageSourceCredentials_BitzOrcasCommercial 的值。

锁文件失败

CI 的 ContinuousIntegrationBuild=true 会启用 locked mode。先查看差异:

Terminal window
git diff -- '**/packages.lock.json' Directory.Packages.props
dotnet restore <Name>.slnx -p:RestoreLockedMode=false
git diff -- '**/packages.lock.json'

第二条命令只用于在受控升级分支更新候选锁文件。审阅版本、源与传递闭包后提交;不要在 CI 删除锁文件或长期关闭 locked mode。

Build 找不到类型或扩展方法

先确保 Restore 与 Build 使用同一 SDK、同一工作目录和同一锁文件:

Terminal window
dotnet --version
dotnet restore <Name>.slnx
dotnet build <Name>.slnx --configuration Release --no-restore

然后检查:

  • Directory.Packages.props 是否被局部项目版本覆盖;
  • Profile 包与 Generator 包是否来自同一版本;
  • 客户是否删除了生成属性、Module marker 或 Endpoint assembly;
  • Source Generator 的编译诊断是否被前面的错误掩盖;
  • 项目引用是否仍为 Host → Application → Contracts。

不要通过给 Application 添加 ORM/Host 引用来“修复”生成错误;这会转化为架构违规。

ORM 与命令选择不一致

Terminal window
# manifest、Host 注册和中央包版本必须指向同一 ORM。
jq -r '.runtimeAdapter' composition-manifest.json
rg -n 'SqlSugar|EfCore' \
src/Hosts/<Name>.Api/Program.cs \
src/Hosts/<Name>.Api/<Name>.Api.csproj \
Directory.Packages.props

SqlSugar 输出应注册 SqlSugar,EF Core 输出应注册 EF Core 并带 EF Schema contribution。若两套 Provider 同时出现或命令/manifest/代码不一致,从空目录重新生成并比较;不要只改 runtimeAdapter 文本。

Architecture Tests 失败

生成的架构测试是产品边界,不是示例噪声。常见违规:

  • Consumer 复制 Framework/Platform 源码;
  • Application 引用 ORM、Host 或基础设施实现;
  • 为聚合建立平行 Entity/Mapper/DataPort;
  • 业务不变量移到 Handler;
  • Owner private 类型泄漏到公开合同;
  • 手写 DI/Endpoint 绕过 Generator;
  • Module 或 Host 项目引用越界。
Terminal window
dotnet test tests/<Name>.Architecture.Tests \
--configuration Release \
--logger 'console;verbosity=detailed'

修复依赖方向或切片结构,不能删除/跳过测试作为长期处理。

Schema Migrator 失败

Single Profile 显式运行 Schema;Multi Profile 从 AppHost 启动同一 API 项目:

Terminal window
dotnet run --project src/Hosts/<Name>.Api -- \
--migrate-schema apply

稳定退出边界:

退出码含义
0操作成功
1执行异常
2action 缺失或无效
3ConnectionStrings:PrimaryDatabase 缺失

SqlSugar 当前采用显式 apply;EF Core 还可按生成 README 使用 plan/status/apply。Schema 模式不加载 JWT、Tenant、License 或 ServiceDefaults,因此这些错误不应阻塞迁移命令。

AppHost 中 API 一直未启动

这是 WaitForCompletion(schema-migrator) 的预期失败关闭行为。按顺序查看:

  1. SQL Server 容器是否健康;
  2. PrimaryDatabase 是否创建;
  3. schema-migrator 日志与退出码;
  4. Migration/DDL 是否有权限、冲突或不兼容;
  5. API 是否仍在等待迁移资源。

不要删除等待关系来获得“绿色”API;先修复 Schema。生产环境也要保持迁移成功先于新版本流量。

Host 启动期配置失败

错误/键原因
ConnectionStrings:PrimaryDatabaseBusiness API 未取得数据库连接
Host.Persistence.Identity.InvalidWorkerId 不在 1..31、DataCenterId 不在 0..31 或缺失
Authentication:Jwt:*Issuer/Audience/SigningKey 缺失,Key 少于 32 bytes
固定租户配置Single Business 的固定租户无效
Host.Licensing.Configuration.Invalid已启用 License 但配置闭包不完整

Multi AppHost 的 user-secrets 参数名是 Parameters:persistence-worker-id 和 Parameters:persistence-data-center-id。直接运行 API 时则提供 Persistence:WorkerId、Persistence:DataCenterId。

Authorization Profile 失败

Authorization 比中性 Business 多四类前置:

  • RabbitMQ Host/User/Password/Port 或 Aspire ConnectionStrings:rabbitmq;
  • Authorization persistence Provider 与 Host ORM 一致;
  • 独立的 Authorization operations WorkerId/DataCenterId;
  • bootstrap tenant 与 subject key。

Multi AppHost 的顺序为 Schema → authorization-bootstrap → API。任何一次性资源失败都会阻止 API。先看对应资源日志,不要把它当作普通 default-business-multi 排障。

Health 返回 503

三个端点不能互相替代:

路径503 的主要范围
/health/live进程活性检查失败
/health/ready基础运行依赖未就绪
/health/licenseRuntime License 缺失、过期、签名/策略/缓存失败

/health/ready 不会只因 License 缺失失败。发布平台若要求 License 门禁,应单独探测 /health/license 或组合两者。

Scalar/OpenAPI 无法访问

检查 OpenApi:Enabled、Environment 与访问保护:

Terminal window
curl -i http://localhost:<port>/openapi/v1.json
curl -i http://localhost:<port>/scalar/v1

Development 默认启用;非 Development 默认不应假设开放。启用 RequireAuthentication 时,交互文档登录入口与 API Bearer 是不同认证面,详见 OpenAPI 与 Scalar。

验证确定性

怀疑模板漂移时,在两个空目录使用完全相同命令:

Terminal window
# 两次使用相同名称、Profile、ORM 和空目录。
base="$(mktemp -d)"
for n in one two; do
dotnet new bitzorcas-host -n Deterministic -o "$base/$n" \
--ProfileChoice default-business-single \
--RuntimeAdapter efcore
done
# 递归 diff 应无输出;任何差异都进入模板缺陷证据。
diff -ru "$base/one" "$base/two"

真实运行的确定性验证(两次生成后递归 diff,退出码 0 即逐字节一致):

bitzorcas-host session
$ 
已成功创建模板“BitzOrcas.Modern Solution Template”。
$ dotnet new bitzorcas-host -n Deterministic -o /tmp/gen/two --ProfileChoice default-business-single --RuntimeAdapter efcore
已成功创建模板“BitzOrcas.Modern Solution Template”。
$ diff -ru /tmp/gen/one /tmp/gen/two
$ echo $?
0

有差异时记录模板包版本、SDK、OS 和完整命令,作为模板缺陷提交。无差异而业务仓库不同,继续调查手工修改、合并结果和旧文件。

安全证据包

提交问题前收集:

Terminal window
# 环境、Help 与源列表不含 Secret,可直接生成基础证据。
dotnet --info > dotnet-info.txt
dotnet new bitzorcas-host --help > template-help.txt
dotnet nuget list source > nuget-sources.txt
# 组合摘要与 Build 日志发送前仍需执行敏感信息扫描。
jq '{profileChoice,runtimeAdapter,hosts,projects}' \
composition-manifest.json > composition-summary.json
dotnet build <Name>.slnx --configuration Release \
--verbosity normal > build.log 2>&1

发送前扫描 Token、连接串、JWT Key、License、用户目录和内部 URL。优先提供错误前后有限日志、退出码、精确 Commit/模板版本和可复现命令。

另见

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%