Skip to content
bitzorcas
中EN

Concept

Master Data 主数据与参考目录

源码校验 MasterData 的九张参考目录行、八组 CSV 种子、字典解析器、租户缓存、宿主组合和当前产品边界。

Last updated

Master Data 当前不是一套带审批、版本、质量规则和管理后台的主数据管理平台。它物理拥有九张租户化参考目录行、八个 CSV seed step,应用共享的 IDataDictionaryResolver 实现,以及一个只读治理查询入口。Infrastructure 仍是数据 owner,但 Contracts 与 Application 项目已经存在,用于暴露治理报告。

1. 当前产品面

8 个嵌入 CSV

8 个 EntitySet seed step

9 张 CatalogRecord 表

MasterDataDictionaryResolver

应用字段显示

编译期 Bitz 元数据

API/JobHost 组合

SysTranslationCatalogRecord 是第九张表,但没有 MasterData CSV/seed step;I18n 模块通过它提供翻译读写能力。

2. 物理结构

src/Platform/MasterData/
└── BitzOrcas.Platform.MasterData.Infrastructure/
├── Persistence/ # 9 个 CatalogRecord
├── Seeders/ # 8 个 ORM 中立 seed step
│ └── Assets/ # 8 个 ^ 分隔 CSV
├── Dictionary/
│ └── MasterDataDictionaryResolver.cs
├── MasterDataDependencyInjection.cs
├── MasterDataFeatures.cs
├── MasterDataPermissions.cs
└── MasterDataModule.cs

它引用 Application、Infrastructure、Persistence.Models 与编译期 Metadata Generator,但不引用 SqlSugar/EF Core adapter 程序集。

3. 九类参考目录

行类型表当前用途
SysLanguageCatalogRecordSysLanguage租户语言目录,I18n 读取
SysCountryCatalogRecordSysCountryISO 国家/地区字段
SysIndustrySettingCatalogRecordSysIndustrySetting行业树
SysGeneralCodeGroupCatalogRecordSysGeneralCodeGroup字典组层级
SysGeneralCodeCatalogRecordSysGeneralCode字典代码、组、层级和显示名
SysGeneralCodeTextCatalogRecordSysGeneralCodeText字典本地化显示名
SysExchangeRateCatalogRecordSysExchangeRate币种对日期快照
SysPublicHolidayCatalogRecordSysPublicHoliday国家/年份节假日
SysTranslationCatalogRecordSysTranslationI18n 多级作用域翻译

所有行继承 BizEntityBase,都标注 IsTenant=true 与 IsSoftDelete=true。

4. 所有权迁移为什么重要

旧实现曾把这些行和 SqlSugar 专属 seeder 放在 Framework。当前架构测试要求它们保持删除,并由 MasterData owner 本地拥有。这样做让 Framework 不再承载业务参考数据,也让同一 seed step 可以通过 IEntitySet<T> 运行于不同 ORM。

MasterData 是 ADR 统一聚合规则的显式“多表参考目录例外”。这些 record 不是待恢复的 *Entity.cs + mapper 模式。

5. 宿主组合真相

API 项目显式引用 MasterData Infrastructure,并在 PersistenceRegistration 调用:

当前非仓储服务注册
// ① ORM adapter 先通过编译期注册表提供九种 IEntitySet<T>。
services.AddBitzOrcasGeneratedPersistenceAdapters(persistenceProvider);
// ② MasterData 自己只注册字典解析器,不注册仓储或端点。
services.AddBitzOrcasMasterDataPlatform();
// ③ 通用种子框架与生成式 seed manifest 决定是否执行八个步骤。
services.AddBitzOrcasSeeders(configuration);
services.AddBitzOrcasGeneratedSeedSteps();

JobHost 也引用该项目。仅有项目引用不表示会自动执行种子;仍取决于种子编排配置和宿主生命周期。

6. 字典读取真实 API

MasterDataDictionaryResolver 实现共享 IDataDictionaryResolver:

方法行为
ResolveAsync(group, code, culture)命中返回显示名,未命中返回原 code
ResolveListAsync(group, csvCodes, culture)按输入顺序解析逗号列表
ResolveBatchAsync(requests, culture)按 group 分组加载并返回 request→文本
ListEntriesAsync(group, culture)列出启用、未删除项并按 Sort 排序
InvalidateCacheAsync(group?)不论 group 参数,清除整个 dictionary tag

原文档中的 ReferenceKey、ReferenceValue? 和 resolver.ResolveAsync(stableKey, ...) 并不存在,已删除。

7. 正确消费示例

保存代码,读取时解析文本
// ① 业务行保存稳定 code;不要保存可能变化的显示文案。
order.PaymentMethodCode = request.PaymentMethodCode;
await orders.UpdateAsync(order, cancellationToken);
// ② 读取投影时使用真实签名 groupKey + code + culture。
var displayName = await dictionaries.ResolveAsync(
groupKey: "PAYMENTMETHODCODE",
code: order.PaymentMethodCode,
culture: currentCulture.Name,
cancellationToken);
// ③ Resolver 未命中会返回原 code,因此 API 同时返回二者。
return new PaymentMethodDto(order.PaymentMethodCode, displayName);

未命中不是 null,也没有 EffectiveCulture 信息。若产品需要区分“翻译缺失”与“显示值恰好等于 code”,当前契约不足。

8. 当前种子资产状态

资产数据行现状
language2
country0(仅表头)
industry0(仅表头)
general-code-group177
general-code43,603
general-code-text0(仅表头)
exchange-rate0(仅表头)
public-holiday347

因此“拥有种子步骤”不等于“每类目录都随产品交付数据”。具体完整性见种子资产与幂等导入。

9. 当前保证与不保证

可以依赖不可假设
九种编译期持久化元数据已有主数据管理 API/UI
seed step ORM 中立CSV 表头/内容严格校验通过
字典缓存键带 Tenant scopegroup 定向失效只影响当前租户
code 比较大小写不敏感culture 有规范化与回退链
缺失 code 返回原值可识别缺失原因
API Host 注册 resolverFeature/Permission 已在入口强制

10. 已确认风险

  1. SysGeneralCodeText seed 的自然键和 Resolver 查询只用 Code+Language,忽略 Class/Group,存在碰撞。
  2. 本地化结果以 Code 建字典,重复 Code 会抛 ToDictionary 异常。
  3. 任意 group 的失效都会清整个 dictionary tag。
  4. ListEntriesAsync 绕过 30 分钟组缓存。
  5. CSV 读取关闭严格 Header/MissingField 校验,关键列异常只告警。
  6. 汇率 CSV 是 UpdateDate,模型/WhereColumns 是拼写遗留 ModifyTimee。
  7. 四个资产只有表头,但 seed 执行可以记录“upserted 0”并成功。
  8. 43,603 个 code 逐行查询/写入,冷启动成本和事务边界需压测。

11. 文档导航

12. 治理查询入口

GET /api/master-data/governance(资源 master-data/catalog、动作 Read)是一个 owner-local 只读治理报告,供运营了解各参考目录的规模和字典内容。查询参数:GroupCode(可选,选定某个字典组)、Culture(可选,BCP-47)、Search(可选)、EntryLimit(默认 100,上限 200)。

返回 MasterDataGovernanceReport:

  • Catalogs:九个目录的计数摘要(languages、countries、industries、dictionaryGroups、dictionaryEntries、dictionaryTexts、exchangeRates、publicHolidays、translations),每项给出 Total/Active/SeedManaged;
  • DictionaryGroups 与 Entries:当选定 GroupCode 时,分页返回该组下的字典条目(含本地化 DisplayName);
  • SelectedGroup、SelectedGroupTotal、Culture、EntryLimit、GeneratedAt。

读存储 MasterDataGovernanceReadStore 在 Infrastructure 层实现 IMasterDataGovernanceReadStore,全部通过 IEntitySet<T> 投影;未注册时降级为 fail-closed 的 UnavailableMasterDataGovernanceReadStore。错误码:MasterData.Governance.StoreUnavailable(ServiceUnavailable)、MasterData.Governance.InvalidQuery(Validation)。

这条入口与 Operations 的适配器/连接器报告同类:只读投影,不做主动健康探测,回答”有多少、是什么”,不回答”是否正确、是否最新”。

13. 源码核查

Terminal window
# 核对九张表、八个 seed step 与八个资产。
find src/Platform/MasterData -type f | sort
# 确认默认 Host 的实际组合位置。
rg -n "AddBitzOrcasMasterDataPlatform|AddBitzOrcasGeneratedSeedSteps" src/Hosts -g '*.cs'
# 旧 Framework/Entity 所有权应无命中。
find src/Framework src/Platform/MasterData -path '*MasterData*Entity.cs' -o -path '*SqlSugar*MasterData*'

返回平台模块目录 · I18n 模块

100%

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