重构TClientDataSet

3

一个TClientDataSet的XML文件能否在不丢失数据的情况下进行重构?是否有演示应用程序或源代码展示如何进行这样的重构?

2个回答

1

是和不是,XML文档使用XLST进行转换,因此需要符合该模板才能被TClientDataSet读取。

但这也意味着您可以将文档转换为任何您喜欢的格式,并将其转换为单独的文档,只是不能直接将转换后的文档加载到TClientDataSet中。

编辑: 哎呀,忘记发布一个例子了。

此项目在代码中心显示了从客户端数据集到ADO记录集的转换。


0
为了在磁盘上更改CDS结构,我使用了下面概述的子类。我们将数据以二进制格式写入流中(在压缩/加密之前),但对于XML格式应该也可以使用相同的方法。
如果您需要添加/删除任何字段或更改字段定义,则只需增加数据集表版本。每次打开数据集时,它都会将保存的版本号与当前版本进行比较。如果保存的表旧,则会将其复制到新结构中,因此如果您需要进行更改,则第一次重新加载表时会有一定的性能损失,但之后它应该像往常一样从磁盘加载。
因此,如果您在合并后将CDS保存回磁盘-哇-您的XML结构已更新,以CDS友好的格式呈现。
TCDS = class(TCustomClientDataset)
private
 fTableVersion: integer;
 /// <summary> Copies records from source with potentially different table
 ///  structure/field defs from self, providing defaults for missing fields</summary>
 procedure CopyFromDataset(const ASource: TCustomClientDataset);
 /// <summary>Provide a default value, if necessary, for any new fields</summary>
 function GetDefaultValue(const AFieldName: string): variant;
public
 procedure LoadFromStream(AStream: TStream);
 procedure SaveToStream(AStream: TStream);
end;

procedure TCDS.LoadFromStream(AStream: TStream);
var
 ATemp: TCDS;
 APersistedVersion: integer;
begin
 AStream.ReadData(APersistedVersion);
 if APersistedVersion = fTableVersion then
 begin
  Close;
  ReadDataPacket(AStream, True);
  Open;
 end
 else if APersistedVersion < fTableVersion then
 begin
  // It's an old table structure:
  // - Load old structure into temp CDS
  // - Merge temp CDS records into new structure
  ATemp := TCDS.Create;
  try
   ATemp.Close;
   ATemp.ReadDataPacket(AStream, True);
   ATemp.Open;
   CopyFromDataset(ATemp);
  finally
   FreeAndNil(ATemp);
  end;
 end;
end;

procedure TCDS.SaveToStream(AStream: TStream);
begin
 AStream.WriteData(fVersionNumber);
 WriteDataPacket(AStream, True);
end;

procedure TCDS.CopyFromDataset(const ASource: TCustomClientDataset);
var
 ACurrentFieldNames: TStrings;
 i: integer;
begin
 // Assuming we don't want to keep any records already in dataset
 EmptyDataSet;
 ACurrentFieldNames := TStringList.Create;
 try
  Fields.GetFieldNames(ACurrentFieldNames);
  for i := 0 to ACurrentFieldNames.Count-1 do
   ACurrentFieldNames.Objects[i] := ASource.Fields.FindField(ACurrentFieldNames[i]);

  ASource.First;
  while not ASource.Eof do
  begin
   Append;
   for i := 0 to Fields.Count-1 do
   begin
    if Assigned(ACurrentFieldNames.Objects[i]) then
     Fields[i].Value := TField(ACurrentFieldNames.Objects[i]).Value
    else if Fields[i].Required then
     Fields[i].Value := GetDefaultValue(ACurrentFieldNames[i]);
    end;
    Post;
    ASource.Next;
   end;
 finally
  FreeAndNil(ACurrentFieldNames);
 end;
end; 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接