代码之家  ›  专栏  ›  技术社区  ›  bill

重新构造tclientdataset

  •  3
  • bill  · 技术社区  · 16 年前

    重新编译XML文件可以不丢失数据吗?有没有演示应用程序或源代码来演示如何进行这种重组?

    2 回复  |  直到 8 年前
        1
  •  1
  •   Tim Jarvis    16 年前

    是和否,xml文档是使用xlst转换的,因此它需要符合该模板才能被tclientdataset读取。

    但是,这也意味着您也可以将DOC转换成您喜欢的任何格式,成为单独的DOC,您不能将转换后的DOC直接加载到Tclipse数据集中。

    编辑: 哎呀,忘了贴个例子了。

    This project 在代码中心显示从clientdataset到ado记录集的转换。

        2
  •  0
  •   Phil B    8 年前

    为了更改磁盘上的cds结构,我使用了下面列出的一个子类。我们以二进制格式将数据写入流(在压缩/加密之前),但是对于XML格式,它的工作原理应该是一样的。

    如果需要从保存的数据集中添加/删除任何字段或更改字段定义,则只需增加数据集表的版本。每次打开数据集时,它都会将保存的版本号与当前版本号进行比较。如果保存的表是旧的,它将被复制到新的结构中,因此如果需要进行更改,则在第一次重新加载表时会受到一次性能影响,但在这之后,它应该像往常一样从磁盘加载。

    因此,如果在执行merge-voila之后将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;