Delphi 重新构造TClientdataset
TClientDataSet XML文件是否可以在不丢失数据的情况下重新构造?是否有演示应用程序或源代码显示如何进行这种重构?是和否,xml文档使用XLST进行转换,因此它需要符合该模板才能被TClientDataSet读取 然而,这也意味着您可以将文档转换为您喜欢的任何格式,并将其转换为单独的文档,您只是不能将转换后的文档直接加载到TClientDataSet中 编辑: 哎呀,忘了发一个例子了Delphi 重新构造TClientdataset,delphi,tclientdataset,Delphi,Tclientdataset,TClientDataSet XML文件是否可以在不丢失数据的情况下重新构造?是否有演示应用程序或源代码显示如何进行这种重构?是和否,xml文档使用XLST进行转换,因此它需要符合该模板才能被TClientDataSet读取 然而,这也意味着您可以将文档转换为您喜欢的任何格式,并将其转换为单独的文档,您只是不能将转换后的文档直接加载到TClientDataSet中 编辑: 哎呀,忘了发一个例子了 在代码中心显示了从clientdataset到ADO记录集的转换。为了更改磁盘上的CDS结构,我使用
在代码中心显示了从clientdataset到ADO记录集的转换。为了更改磁盘上的CDS结构,我使用了下面概述的子类。我们以二进制格式将数据写入流(在压缩/加密之前),但对于XML格式,其工作原理应该大致相同 如果需要从保存的数据集中添加/删除任何字段或更改字段定义,则只需增加数据集表的版本。每次打开数据集时,它都会将保存的版本号与当前版本号进行比较。如果保存的表是旧的,它将被复制到新的结构中,因此如果您需要进行更改,第一次重新加载表时将受到一次性能影响,但之后应像往常一样从磁盘加载 因此,如果在执行合并操作后将CD保存回磁盘,那么XML结构将以CD友好的格式更新
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;
TCDS=class(TCustomClientDataset)
私有的
fTableVersion:整数;
///从具有潜在不同表的源复制记录
///结构/字段从self定义,为缺少的字段提供默认值
过程CopyFromDataset(const ASource:TCustomClientDataset);
///如有必要,为任何新字段提供默认值
函数GetDefaultValue(const AFieldName:string):变量;
公众的
程序加载源流(AStream:TStream);
程序保存到流(AStream:TStream);
结束;
程序TCDS.LoadFromStream(AStream:TStream);
变量
ATemp:中药;
APersistedVersion:整数;
开始
AStream.ReadData(辅助版本);
如果APersistedVersion=fTableVersion,则
开始
接近;
ReadDataPacket(AStream,True);
打开
结束
否则,如果辅助版本<故障诊断版本,则
开始
//这是一个旧的表结构:
//-将旧结构加载到临时CD中
//-将临时CD记录合并到新结构中
ATemp:=TCDS.Create;
尝试
ATemp.关闭;
ATemp.ReadDataPacket(AStream,True);
ATemp.打开;
CopyFromDataset(ATemp);
最后
自由零(ATemp);
结束;
结束;
结束;
程序TCDS.SaveToStream(AStream:TStream);
开始
AStream.WriteData(fVersionNumber);
WriteDataPacket(AStream,True);
结束;
过程TCDS.CopyFromDataset(const ASource:TCustomClientDataset);
变量
acurrenfieldnames:TStrings;
i:整数;
开始
//假设我们不想在数据集中保留任何记录
空数据集;
acurrenfieldnames:=TStringList.Create;
尝试
字段。GetFieldName(acurrenfieldnames);
对于i:=0到acurrenfieldnames.Count-1 do
acurrenfieldnames.Objects[i]:=ASource.Fields.FindField(acurrenfieldnames[i]);
A来源:第一;
而不是一个资源。Eof做什么
开始
追加
对于i:=0到Fields.Count-1 do
开始
如果已分配(acurrenfieldnames.Objects[i]),则
字段[i]。值:=TField(ACurrentFieldNames.Objects[i])。值
否则,如果字段[i]为必填项,则
字段[i]。值:=GetDefaultValue(ACurrentFieldNames[i]);
结束;
邮递
A来源。下一步;
结束;
最后
FreeAndNil(acurrenfieldnames);
结束;
结束;