Delphi 12动态创建嵌套TClientDataSet后LoadFromFile异常求助
Delphi 12动态创建嵌套TClientDataSet后LoadFromFile无法激活子数据集
原有场景
设计阶段创建两个嵌套的TClientDataSet:VertaalData(主数据集)和VertaalRegelsData(子数据集),已配置好字段定义等属性,调用LoadFromFile可正常加载并使用数据。
新场景
改为运行时动态构建数据集结构(无设计期预设属性),再加载同一份数据文件,代码如下:
with VertaalData do // 嵌套数据集 begin if Active then Close; FieldDefs.Clear; FieldDefs.Add(sVersion, ftString, 11, False); // s...为字段名常量 with FieldDefs.AddFieldDef do begin Name := sTranslate; DataType := ftDataSet; ChildDefs.Add(sID, ftInteger); ChildDefs.Add(sTranslate, ftBoolean); ChildDefs.Add(STT_NL, ftString, 250, False); // STT为字段名常量 ChildDefs.Add(STT_EN, ftString, 250, False); ChildDefs.Add(STT_DE, ftString, 250, False); ChildDefs.Add(STT_XX, ftString, 250, False); end; CreateDataSet; LoadFromFile(LLanguageFileName); end;
异常情况
与设计期创建的结构相比,出现以下问题:
CreateDataSet执行后,VertaalRegelsData.DataSetField未自动填充;LoadFromFile执行后,主数据集VertaalData处于dsBrowse状态并定位到首条记录,但子数据集VertaalRegelsData始终为dsInactive状态。
已尝试在CreateDataSet后添加以下代码关联子数据集:
VertaalRegelsData.DataSetField := TDataSetField(VertaalData.FieldByName(sTranslate));
(提前添加会提示「字段未知」)但仍无法激活子数据集。
尝试过的无效方法
- 调用
VertaalRegelsData.Open→ 提示「Missing data provider or data packet」; - 调用
VertaalRegelsData.First→ 提示「Cannot perform this operation on a closed dataset」; - 读取
VertaalData的字段值; - 调用
VertaalData.First。
补充信息
- 环境:64位Delphi 12 VCL应用;
- 数据文件由另一程序通过以下代码生成:
NewLanguageData.Post; // 转换后处于dsEdit状态 NewLanguageLineData.DisableControls; NewLanguageData.MergeChangeLog; NewLanguageData.SaveToFile(ChangeFileExt(SaveDialogLanguage.FileName, '.lng'));
- 另有第三方查看此类
TClientDataSet文件的工具,同样无法打开嵌套的子数据集。
解决方案
1. 同步子数据集的字段定义
设计期创建的嵌套数据集会自动同步子数据集的字段定义,但动态创建时需手动对齐。在关联DataSetField后,显式从主数据集的子字段复制定义并创建子数据集:
with VertaalData do begin // 原有创建FieldDefs的代码 FieldDefs.Clear; FieldDefs.Add(sVersion, ftString, 11, False); with FieldDefs.AddFieldDef do begin Name := sTranslate; DataType := ftDataSet; ChildDefs.Add(sID, ftInteger); ChildDefs.Add(sTranslate, ftBoolean); ChildDefs.Add(STT_NL, ftString, 250, False); ChildDefs.Add(STT_EN, ftString, 250, False); ChildDefs.Add(STT_DE, ftString, 250, False); ChildDefs.Add(STT_XX, ftString, 250, False); end; CreateDataSet; // 关联子数据集并同步字段定义 VertaalRegelsData.DataSetField := TDataSetField(FieldByName(sTranslate)); VertaalRegelsData.FieldDefs.Assign(TDataSetField(FieldByName(sTranslate)).ChildDefs); VertaalRegelsData.CreateDataSet; LoadFromFile(LLanguageFileName); end;
2. 加载后触发子数据集激活
LoadFromFile仅激活主数据集,需通过主数据集的记录切换触发子数据集加载,或显式激活:
LoadFromFile(LLanguageFileName); if VertaalData.Active then begin // 重新定位主数据集记录,触发子数据集绑定 VertaalData.First; VertaalData.Last; VertaalData.First; // 显式打开子数据集 if Assigned(VertaalRegelsData.DataSetField) then VertaalRegelsData.Open; end;
3. 优化数据文件生成逻辑
确保生成文件时子数据集处于正常激活状态,避免结构缺失:
NewLanguageData.Post; NewLanguageLineData.EnableControls; NewLanguageLineData.Active := True; // 确保子数据集激活 NewLanguageData.MergeChangeLog; NewLanguageData.SaveToFile(ChangeFileExt(SaveDialogLanguage.FileName, '.lng'));
4. 避免with语句的上下文混淆
with可能导致字段定义赋值时的上下文错误,改为显式引用更可靠:
VertaalData.Close; VertaalData.FieldDefs.Clear; VertaalData.FieldDefs.Add(sVersion, ftString, 11, False); var DataSetFieldDef := VertaalData.FieldDefs.AddFieldDef; DataSetFieldDef.Name := sTranslate; DataSetFieldDef.DataType := ftDataSet; DataSetFieldDef.ChildDefs.Add(sID, ftInteger); DataSetFieldDef.ChildDefs.Add(sTranslate, ftBoolean); DataSetFieldDef.ChildDefs.Add(STT_NL, ftString, 250, False); DataSetFieldDef.ChildDefs.Add(STT_EN, ftString, 250, False); DataSetFieldDef.ChildDefs.Add(STT_DE, ftString, 250, False); DataSetFieldDef.ChildDefs.Add(STT_XX, ftString, 250, False); VertaalData.CreateDataSet;
内容的提问来源于stack exchange,提问作者Jan Doggen
相关产品推荐
相关产品推荐

