【调整】cfg生成中branch相关名称改为patch

main
walon 2021-09-07 16:34:58 +08:00
parent 62511c10f2
commit 614ebb6442
12 changed files with 102 additions and 100 deletions

View File

@ -74,17 +74,19 @@ Luban工具有两种部属方式。
--input_data_dir <input data dir> 必选参数。 配置数据文件根目录。
-c,--output_code_dir <output code dir> 可选参数。 生成代码文件的目录。
-s,--service 必选参数。生成分组目标。一般来说会定义client,server,editor等好几个目标不同目标的生成内容不同。
--gen_types <type1,type2,,,> 必选参数。生成任务类型。既可以是生成代码也可以是生成数据或者其他。目前支持的有 code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_go_bin,code_go_json,code_cpp_bin,code_python27_json,code_python3_jsoncode_typescript_bin,code_typescript_json,data_bin,data_lua,data_json,data_json_monolithic
--gen_types <type1,type2,,,> 必选参数。生成任务类型。既可以是生成代码也可以是生成数据或者其他。目前支持的有 code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_go_bin,code_go_json,code_cpp_bin,code_python27_json,code_python3_jsoncode_typescript_bin,code_typescript_json,data_bin,data_lua,data_json,data_json_monolithic,data_template
--output_data_dir <output data dir> 可选参数。 导出的数据文件的目录。
--validate_root_dir <path validate root dir>. 可选参数。 配置path检查的根目录。
--export_test_data 可选参数。 是否导出测试数据。默认为false
--template_name <template name> 可选参数。数据模板的名称不包含后缀当gen_types包含 data_template时必须指定。
--data_file_extension <output data file extension> 可选参数。 导出数据文件的后缀。默认按照生成类型自动选择。
-t,--l10n_timezone <timezone> 可选参数。 指定所在时区。影响datetime类型转换为utc时间。 默认为中国北京时间。
--input_l10n_text_files <file1,file2..> 可选参数。 本地化的文本映射表。可以有多个。
--l10n_text_field_name <field name> 可选参数。 文本映射表中目标映射列的列名默认为text
--output_l10n_not_converted_text_file <file> 可选参数。 未被本地化映射的text key和value的输出文件。不提供该参数则不生成
--branch <branch name> 可选参数。当前需要生成的分支名称。
--branch_input_data_dir <branch data root dir> 可选参数。分支数据的根目录。
--output_l10n_not_translated_text_file <file> 可选参数。 未被本地化映射的text key和value的输出文件。不提供该参数则不生成
--patch <patch name> 可选参数。当前需要生成的分支名称。
--patch_input_data_dir <patch data root dir> 可选参数。分支数据的根目录。
## 示例

View File

@ -81,7 +81,7 @@ namespace Luban.Job.Cfg.Cache
var cacheAss = cacheInfo.Table.Assembly;
var curAss = table.Assembly;
if (cacheAss.TimeZone == curAss.TimeZone
&& cacheAss.TargetBranch == null && curAss.TargetBranch == null
&& cacheAss.TargetPatch == null && curAss.TargetPatch == null
&& !cacheAss.NeedL10nTextTranslate && !curAss.NeedL10nTextTranslate
&& records.Count == cacheInfo.Records.Count && records.SequenceEqual(cacheInfo.Records))
{
@ -97,7 +97,7 @@ namespace Luban.Job.Cfg.Cache
public void AddCachedRecordOutputData(DefTable table, List<Record> records, string dataType, string md5)
{
var curAss = table.Assembly;
if (curAss.TargetBranch == null && !curAss.NeedL10nTextTranslate)
if (curAss.TargetPatch == null && !curAss.NeedL10nTextTranslate)
{
_tableCaches[(table.FullName, dataType)] = (table, records, md5);
s_logger.Debug("add output data cache. table:{} dataType:{} md5:{}", table.FullName, dataType, md5);

View File

@ -26,7 +26,7 @@ namespace Luban.Job.Cfg.Defs
private readonly List<string> _importExcelBeanFiles = new();
private readonly List<Branch> _branches = new();
private readonly List<Patch> _patches = new();
private readonly List<Table> _cfgTables = new List<Table>();
@ -39,7 +39,7 @@ namespace Luban.Job.Cfg.Defs
public CfgDefLoader(RemoteAgent agent) : base(agent)
{
RegisterRootDefineHandler("importexcel", AddImportExcel);
RegisterRootDefineHandler("branch", AddBranch);
RegisterRootDefineHandler("patch", AddPatch);
RegisterRootDefineHandler("service", AddService);
RegisterRootDefineHandler("group", AddGroup);
@ -54,7 +54,7 @@ namespace Luban.Job.Cfg.Defs
return new Defines()
{
TopModule = TopModule,
Branches = _branches,
Patches = _patches,
Consts = this._consts,
Enums = _enums,
Beans = _beans,
@ -87,20 +87,20 @@ namespace Luban.Job.Cfg.Defs
}
}
private static readonly List<string> _branchRequireAttrs = new List<string> { "name" };
private void AddBranch(XElement e)
private static readonly List<string> _patchRequireAttrs = new List<string> { "name" };
private void AddPatch(XElement e)
{
ValidAttrKeys(RootXml, e, null, _branchRequireAttrs);
var branchName = e.Attribute("name").Value;
if (string.IsNullOrWhiteSpace(branchName))
ValidAttrKeys(RootXml, e, null, _patchRequireAttrs);
var patchName = e.Attribute("name").Value;
if (string.IsNullOrWhiteSpace(patchName))
{
throw new Exception("branch 属性name不能为空");
throw new Exception("patch 属性name不能为空");
}
if (this._branches.Any(b => b.Name == branchName))
if (this._patches.Any(b => b.Name == patchName))
{
throw new Exception($"branch '{branchName}' 重复");
throw new Exception($"patch '{patchName}' 重复");
}
_branches.Add(new Branch(branchName));
_patches.Add(new Patch(patchName));
}
private static readonly List<string> _groupOptionalAttrs = new List<string> { "default" };
@ -245,7 +245,7 @@ namespace Luban.Job.Cfg.Defs
return mode;
}
private readonly List<string> _tableOptionalAttrs = new List<string> { "index", "mode", "group", "branch_input", "comment", "define_from_file" };
private readonly List<string> _tableOptionalAttrs = new List<string> { "index", "mode", "group", "patch_input", "comment", "define_from_file" };
private readonly List<string> _tableRequireAttrs = new List<string> { "name", "value", "input" };
private void AddTable(string defineFile, XElement e)
@ -259,14 +259,14 @@ namespace Luban.Job.Cfg.Defs
string group = XmlUtil.GetOptionalAttribute(e, "group");
string comment = XmlUtil.GetOptionalAttribute(e, "comment");
string input = XmlUtil.GetRequiredAttribute(e, "input");
string branchInput = XmlUtil.GetOptionalAttribute(e, "branch_input");
string patchInput = XmlUtil.GetOptionalAttribute(e, "patch_input");
string mode = XmlUtil.GetOptionalAttribute(e, "mode");
string tags = XmlUtil.GetOptionalAttribute(e, "tags");
AddTable(defineFile, name, module, valueType, index, mode, group, comment, defineFromFile, input, branchInput, tags);
AddTable(defineFile, name, module, valueType, index, mode, group, comment, defineFromFile, input, patchInput, tags);
}
private void AddTable(string defineFile, string name, string module, string valueType, string index, string mode, string group,
string comment, bool defineFromExcel, string input, string branchInput, string tags)
string comment, bool defineFromExcel, string input, string patchInput, string tags)
{
var p = new Table()
{
@ -291,19 +291,19 @@ namespace Luban.Job.Cfg.Defs
}
p.InputFiles.AddRange(input.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)));
if (!string.IsNullOrWhiteSpace(branchInput))
if (!string.IsNullOrWhiteSpace(patchInput))
{
foreach (var subBranchStr in branchInput.Split('|').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)))
foreach (var subPatchStr in patchInput.Split('|').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)))
{
var nameAndDirs = subBranchStr.Split(':');
var nameAndDirs = subPatchStr.Split(':');
if (nameAndDirs.Length != 2)
{
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' branch_input:'{subBranchStr}' 定义不合法");
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 定义不合法");
}
var branchDirs = nameAndDirs[1].Split(',', ';').ToList();
if (!p.BranchInputFiles.TryAdd(nameAndDirs[0], branchDirs))
var patchDirs = nameAndDirs[1].Split(',', ';').ToList();
if (!p.PatchInputFiles.TryAdd(nameAndDirs[0], patchDirs))
{
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' branch_input:'{subBranchStr}' 子branch:'{nameAndDirs[0]}' 重复");
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 子patch:'{nameAndDirs[0]}' 重复");
}
}
}
@ -470,7 +470,7 @@ namespace Luban.Job.Cfg.Defs
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "define_from_excel", Type = "bool" },
new CfgField() { Name = "input", Type = "string" },
new CfgField() { Name = "branch_input", Type = "string" },
new CfgField() { Name = "patch_input", Type = "string" },
new CfgField() { Name = "tags", Type = "string" },
}
})
@ -505,9 +505,9 @@ namespace Luban.Job.Cfg.Defs
string comment = (data.GetField("comment") as DString).Value.Trim();
bool isDefineFromExcel = (data.GetField("define_from_excel") as DBool).Value;
string inputFile = (data.GetField("input") as DString).Value.Trim();
string branchInput = (data.GetField("branch_input") as DString).Value.Trim();
string patchInput = (data.GetField("patch_input") as DString).Value.Trim();
string tags = (data.GetField("tags") as DString).Value.Trim();
AddTable(file.OriginFile, name, module, valueType, index, mode, group, comment, isDefineFromExcel, inputFile, branchInput, tags);
AddTable(file.OriginFile, name, module, valueType, index, mode, group, comment, isDefineFromExcel, inputFile, patchInput, tags);
};
}
}

View File

@ -15,7 +15,7 @@ namespace Luban.Job.Cfg.Defs
{
public List<Record> MainRecords { get; }
public List<Record> BranchRecords { get; }
public List<Record> PatchRecords { get; }
public List<Record> FinalRecords { get; set; }
@ -34,10 +34,10 @@ namespace Luban.Job.Cfg.Defs
public Dictionary<DType, Record> FinalRecordMap { get; set; }
public TableDataInfo(List<Record> mainRecords, List<Record> branchRecords)
public TableDataInfo(List<Record> mainRecords, List<Record> patchRecords)
{
MainRecords = mainRecords;
BranchRecords = branchRecords;
PatchRecords = patchRecords;
}
}
@ -49,16 +49,16 @@ namespace Luban.Job.Cfg.Defs
public Service CfgTargetService { get; private set; }
private readonly string _branchName;
private readonly string _patchName;
private readonly bool _exportTestData;
public Branch TargetBranch { get; private set; }
public Patch TargetPatch { get; private set; }
public TimeZoneInfo TimeZone { get; }
public DefAssembly(string branchName, TimeZoneInfo timezone, bool exportTestData, RemoteAgent agent)
public DefAssembly(string patchName, TimeZoneInfo timezone, bool exportTestData, RemoteAgent agent)
{
this._branchName = branchName;
this._patchName = patchName;
this.TimeZone = timezone;
this._exportTestData = exportTestData;
this.Agent = agent;
@ -73,7 +73,7 @@ namespace Luban.Job.Cfg.Defs
return groups.Any(g => CfgTargetService.Groups.Contains(g));
}
private readonly List<Branch> _branches = new List<Branch>();
private readonly List<Patch> _patches = new List<Patch>();
private readonly List<Service> _cfgServices = new List<Service>();
@ -95,9 +95,9 @@ namespace Luban.Job.Cfg.Defs
NotConvertTextSet = new NotConvertTextSet();
}
public Branch GetBranch(string name)
public Patch GetPatch(string name)
{
return _branches.Find(b => b.Name == name);
return _patches.Find(b => b.Name == name);
}
public void AddCfgTable(DefTable table)
@ -113,9 +113,9 @@ namespace Luban.Job.Cfg.Defs
return CfgTables.TryGetValue(name, out var t) ? t : null;
}
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> branchRecords)
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
{
_recordsByTables[table.FullName] = new TableDataInfo(mainRecords, branchRecords);
_recordsByTables[table.FullName] = new TableDataInfo(mainRecords, patchRecords);
}
public List<Record> GetTableAllDataList(DefTable table)
@ -184,16 +184,16 @@ namespace Luban.Job.Cfg.Defs
throw new ArgumentException($"service:{outputService} not exists");
}
if (!string.IsNullOrWhiteSpace(_branchName))
if (!string.IsNullOrWhiteSpace(_patchName))
{
TargetBranch = defines.Branches.Find(b => b.Name == _branchName);
if (TargetBranch == null)
TargetPatch = defines.Patches.Find(b => b.Name == _patchName);
if (TargetPatch == null)
{
throw new Exception($"branch '{_branchName}' not in valid branch set");
throw new Exception($"patch '{_patchName}' not in valid patch set");
}
}
this._branches.AddRange(defines.Branches);
this._patches.AddRange(defines.Patches);
foreach (var c in defines.Consts)
{

View File

@ -19,7 +19,7 @@ namespace Luban.Job.Cfg.Defs
Mode = b.Mode;
InputFiles = b.InputFiles;
Groups = b.Groups;
_branchInputFiles = b.BranchInputFiles;
_patchInputFiles = b.PatchInputFiles;
Comment = b.Comment;
Tags = DefUtil.ParseAttrs(b.Tags);
}
@ -37,7 +37,7 @@ namespace Luban.Job.Cfg.Defs
public List<string> InputFiles { get; }
private readonly Dictionary<string, List<string>> _branchInputFiles;
private readonly Dictionary<string, List<string>> _patchInputFiles;
public List<string> Groups { get; }
@ -55,20 +55,20 @@ namespace Luban.Job.Cfg.Defs
public string InnerName => "_" + this.Name;
public List<string> GetBranchInputFiles(string branchName)
public List<string> GetPatchInputFiles(string patchName)
{
return _branchInputFiles.GetValueOrDefault(branchName);
return _patchInputFiles.GetValueOrDefault(patchName);
}
public override void Compile()
{
var ass = Assembly;
foreach (var branchName in _branchInputFiles.Keys)
foreach (var patchName in _patchInputFiles.Keys)
{
if (ass.GetBranch(branchName) == null)
if (ass.GetPatch(patchName) == null)
{
throw new Exception($"table:'{FullName}' branch_input branch:'{branchName}' 不存在");
throw new Exception($"table:'{FullName}' patch_input patch:'{patchName}' 不存在");
}
}

View File

@ -46,12 +46,12 @@ namespace Luban.Job.Cfg
public string TextValueFieldName { get; set; }
[Option("output_l10n_not_translated_text_file", Required = false, HelpText = "the file save not translated l10n texts.")]
public string OutputNotConvertTextFile { get; set; }
public string OutputNotTranslatedTextFile { get; set; }
[Option("branch", Required = false, HelpText = "branch name")]
public string BranchName { get; set; }
[Option("patch", Required = false, HelpText = "patch name")]
public string PatchName { get; set; }
[Option("branch_input_data_dir", Required = false, HelpText = "branch input data root dir")]
public string BranchInputDataDir { get; set; }
[Option("patch_input_data_dir", Required = false, HelpText = "patch input data root dir")]
public string PatchInputDataDir { get; set; }
}
}

View File

@ -76,7 +76,7 @@ namespace Luban.Job.Cfg
return false;
}
if (string.IsNullOrWhiteSpace(options.InputTextTableFiles) ^ string.IsNullOrWhiteSpace(options.OutputNotConvertTextFile))
if (string.IsNullOrWhiteSpace(options.InputTextTableFiles) ^ string.IsNullOrWhiteSpace(options.OutputNotTranslatedTextFile))
{
errMsg = "--input_l10n_text_files must be provided with --output_l10n_not_translated_text_file";
return false;
@ -88,9 +88,9 @@ namespace Luban.Job.Cfg
}
}
if (string.IsNullOrWhiteSpace(options.BranchName) ^ string.IsNullOrWhiteSpace(options.BranchInputDataDir))
if (string.IsNullOrWhiteSpace(options.PatchName) ^ string.IsNullOrWhiteSpace(options.PatchInputDataDir))
{
errMsg = "--branch must be provided with --branch_input_data_dir";
errMsg = "--patch must be provided with --patch_input_data_dir";
return false;
}
@ -140,7 +140,7 @@ namespace Luban.Job.Cfg
TimeZoneInfo timeZoneInfo = string.IsNullOrEmpty(args.TimeZone) ? null : TimeZoneInfo.FindSystemTimeZoneById(args.TimeZone);
var ass = new DefAssembly(args.BranchName, timeZoneInfo, args.ExportTestData, agent)
var ass = new DefAssembly(args.PatchName, timeZoneInfo, args.ExportTestData, agent)
{
UseUnityVectors = args.UseUnityVectors
};
@ -166,7 +166,7 @@ namespace Luban.Job.Cfg
hasLoadCfgData = true;
var timer = new ProfileTimer();
timer.StartPhase("load config data");
await DataLoaderUtil.LoadCfgDataAsync(agent, ass, args.InputDataDir, args.BranchName, args.BranchInputDataDir, args.ExportTestData);
await DataLoaderUtil.LoadCfgDataAsync(agent, ass, args.InputDataDir, args.PatchName, args.PatchInputDataDir, args.ExportTestData);
timer.EndPhaseAndLog();
if (needL10NTextConvert)
@ -221,7 +221,7 @@ namespace Luban.Job.Cfg
{
var notConvertTextList = DataExporterUtil.GenNotConvertTextList(ass.NotConvertTextSet);
var md5 = FileUtil.CalcMD5(notConvertTextList);
string outputNotConvertTextFile = args.OutputNotConvertTextFile;
string outputNotConvertTextFile = args.OutputNotTranslatedTextFile;
CacheManager.Ins.AddCache(outputNotConvertTextFile, md5, notConvertTextList);
genScatteredFiles.Add(new FileInfo() { FilePath = outputNotConvertTextFile, MD5 = md5 });

View File

@ -7,7 +7,7 @@ namespace Luban.Job.Cfg.RawDefs
{
public string TopModule { get; set; } = "";
public List<Branch> Branches { get; set; } = new List<Branch>();
public List<Patch> Patches { get; set; } = new List<Patch>();
public List<Bean> Beans { get; set; } = new List<Bean>();

View File

@ -1,10 +1,10 @@
namespace Luban.Job.Cfg.RawDefs
{
public class Branch
public class Patch
{
public string Name { get; }
public Branch(string name)
public Patch(string name)
{
Name = name;
}

View File

@ -41,6 +41,6 @@ namespace Luban.Job.Cfg.RawDefs
public List<string> InputFiles { get; set; } = new List<string>();
public Dictionary<string, List<string>> BranchInputFiles { get; set; } = new Dictionary<string, List<string>>();
public Dictionary<string, List<string>> PatchInputFiles { get; set; } = new Dictionary<string, List<string>>();
}
}

View File

@ -103,20 +103,20 @@ namespace Luban.Job.Cfg.Utils
}
}
public static async Task LoadTableAsync(RemoteAgent agent, DefTable table, string dataDir, string branchName, string branchDataDir, bool exportTestData)
public static async Task LoadTableAsync(RemoteAgent agent, DefTable table, string dataDir, string patchName, string patchDataDir, bool exportTestData)
{
var mainLoadTasks = new List<Task<List<Record>>>();
var mainGenerateTask = GenerateLoadRecordFromFileTasksAsync(agent, table, dataDir, table.InputFiles, exportTestData, mainLoadTasks);
var branchLoadTasks = new List<Task<List<Record>>>();
var patchLoadTasks = new List<Task<List<Record>>>();
Task branchGenerateTask = null;
if (!string.IsNullOrWhiteSpace(branchName))
Task patchGenerateTask = null;
if (!string.IsNullOrWhiteSpace(patchName))
{
var branchInputFiles = table.GetBranchInputFiles(branchName);
if (branchInputFiles != null)
var patchInputFiles = table.GetPatchInputFiles(patchName);
if (patchInputFiles != null)
{
branchGenerateTask = GenerateLoadRecordFromFileTasksAsync(agent, table, branchDataDir, branchInputFiles, exportTestData, branchLoadTasks);
patchGenerateTask = GenerateLoadRecordFromFileTasksAsync(agent, table, patchDataDir, patchInputFiles, exportTestData, patchLoadTasks);
}
}
@ -129,24 +129,24 @@ namespace Luban.Job.Cfg.Utils
}
s_logger.Trace("== load main records. count:{count}", mainRecords.Count);
List<Record> branchRecords = null;
if (branchGenerateTask != null)
List<Record> patchRecords = null;
if (patchGenerateTask != null)
{
branchRecords = new List<Record>(64);
await branchGenerateTask;
foreach (var task in branchLoadTasks)
patchRecords = new List<Record>(64);
await patchGenerateTask;
foreach (var task in patchLoadTasks)
{
branchRecords.AddRange(await task);
patchRecords.AddRange(await task);
}
s_logger.Trace("== load branch records. count:{count}", branchRecords.Count);
s_logger.Trace("== load patch records. count:{count}", patchRecords.Count);
}
table.Assembly.AddDataTable(table, mainRecords, branchRecords);
table.Assembly.AddDataTable(table, mainRecords, patchRecords);
s_logger.Trace("table:{name} record num:{num}", table.FullName, mainRecords.Count);
}
public static async Task LoadCfgDataAsync(RemoteAgent agent, DefAssembly ass, string dataDir, string branchName, string branchDataDir, bool exportTestData)
public static async Task LoadCfgDataAsync(RemoteAgent agent, DefAssembly ass, string dataDir, string patchName, string patchDataDir, bool exportTestData)
{
var ctx = agent;
List<DefTable> exportTables = ass.Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList();
@ -160,7 +160,7 @@ namespace Luban.Job.Cfg.Utils
genDataTasks.Add(Task.Run(async () =>
{
long beginTime = TimeUtil.NowMillis;
await LoadTableAsync(agent, table, dataDir, branchName, branchDataDir, exportTestData);
await LoadTableAsync(agent, table, dataDir, patchName, patchDataDir, exportTestData);
long endTime = TimeUtil.NowMillis;
if (endTime - beginTime > 100)
{

View File

@ -179,7 +179,7 @@ namespace Luban.Job.Cfg
var tableDataInfo = Assembly.GetTableDataInfo(table);
List<Record> mainRecords = tableDataInfo.MainRecords;
List<Record> branchRecords = tableDataInfo.BranchRecords;
List<Record> patchRecords = tableDataInfo.PatchRecords;
// 这么大费周张是为了保证被覆盖的id仍然保持原来的顺序而不是出现在最后
int index = 0;
@ -187,9 +187,9 @@ namespace Luban.Job.Cfg
{
r.Index = index++;
}
if (branchRecords != null)
if (patchRecords != null)
{
foreach (var r in branchRecords)
foreach (var r in patchRecords)
{
r.Index = index++;
}
@ -205,13 +205,13 @@ namespace Luban.Job.Cfg
{
throw new Exception($"配置表 {table.FullName} 是单值表 mode=one,但主文件数据个数:{mainRecords.Count} != 1");
}
if (branchRecords != null && branchRecords.Count != 1)
if (patchRecords != null && patchRecords.Count != 1)
{
throw new Exception($"配置表 {table.FullName} 是单值表 mode=one,但分支文件数据个数:{branchRecords.Count} != 1");
throw new Exception($"配置表 {table.FullName} 是单值表 mode=one,但分支文件数据个数:{patchRecords.Count} != 1");
}
if (branchRecords != null)
if (patchRecords != null)
{
mainRecords[0] = branchRecords[0];
mainRecords[0] = patchRecords[0];
}
break;
}
@ -228,17 +228,17 @@ namespace Luban.Job.Cfg
");
}
}
if (branchRecords != null)
if (patchRecords != null)
{
var branchRecordMap = new Dictionary<DType, Record>();
foreach (Record r in branchRecords)
var patchRecordMap = new Dictionary<DType, Record>();
foreach (Record r in patchRecords)
{
DType key = r.Data.Fields[table.IndexFieldIdIndex];
if (!branchRecordMap.TryAdd(key, r))
if (!patchRecordMap.TryAdd(key, r))
{
throw new Exception($@"配置表 '{table.FullName}' 分支文件 主键字段:'{table.Index}' 主键值:'{key}' 重复.
1 :{r.Source}
2 :{branchRecordMap[key].Source}
2 :{patchRecordMap[key].Source}
");
}
if (mainRecordMap.TryGetValue(key, out var old))