如何在LoadFromFile之后更改TClientDataSet中fielddef大小的大小

时间:2009-06-29 17:39:26

标签: delphi

在使用LoadFromFile后,我无法在TClientDataSet中更改fielddef的大小。 有没有人有一个很好的方法来改变给定ClientDataSet的大小,但仍保留所有其他东西。

2 个答案:

答案 0 :(得分:3)

实现TDataSet的方式有虚拟方法来分配和释放记录缓冲区,以及从该缓冲区获取和设置值。大多数数据集后代为缓冲区保留一块连续内存,因此如果您的三个字段长度为4,6和20个字节,则字段1将从位置0开始,字段2从位置4开始,字段3从位置10开始。

如果要在数据集打开时更改字段大小,则必须调整所有这些缓冲区的大小并进行调整,否则您将遇到麻烦。没有虚拟方法来调整缓冲区的大小,所以我认为它可能不可行。

解决此问题的方法是将您的内容从原始CDS复制到具有不同字段大小的新内容。按值分配值,或使用TDataSetProvider。如果您使用提供程序(最佳方法)并且您不知道确切的定义,则仍需要迭代源数据集字段并将其添加到具有正确大小的目标。

答案 1 :(得分:1)

您可以使用旧数据集的FieldDef创建新数据集关键点为TFieldDefs.Assign。这是一个小例子:

// insert test data
procedure TForm1.InsertRecord(DataSet: TDataSet; ID: Integer; const Name: string);
begin
  DataSet.Insert;
  try
    DataSet.Fields[0].AsInteger := ID;
    DataSet.Fields[1].AsString := Name;
    DataSet.Post;
  except
    DataSet.Cancel;
    raise;
  end;
end;

// create the original dataset
procedure TForm1.Button1Click(Sender: TObject);
var
  DataSet: TClientDataSet;
begin
  DataSet := TClientDataSet.Create(nil);
  try
    DataSet.FieldDefs.Add('ID', ftInteger);
    DataSet.FieldDefs.Add('NAME', ftString, 20);
    DataSet.CreateDataSet;
    DataSet.LogChanges := False;
    InsertRecord(DataSet, 1, 'Hello');
    InsertRecord(DataSet, 2, 'World!');
    DataSet.SaveToFile(ExtractFilePath(Application.ExeName) + 'old.xml', dfXML);
  finally
    DataSet.Free;
  end;
end;

// create the new dataset
procedure TForm1.Button2Click(Sender: TObject);
var
  OldDataSet, NewDataSet: TClientDataSet;
begin
  OldDataSet := nil;
  NewDataSet := nil;
  try
    OldDataSet := TClientDataSet.Create(nil);
    OldDataSet.LoadFromFile(ExtractFilePath(Application.ExeName) + 'old.xml');

    NewDataSet := TClientDataSet.Create(nil);
    NewDataSet.FieldDefs.Assign(OldDataSet.FieldDefs);
    NewDataSet.FieldDefs[1].Size := 30;
    NewDataSet.CreateDataSet;
    NewDataSet.LogChanges := False;

    OldDataSet.First;
    while not OldDataSet.EOF do
    begin
      InsertRecord(NewDataSet, OldDataSet.Fields[0].AsInteger, OldDataSet.Fields[1].AsString);

      OldDataSet.Next;
    end;

    NewDataSet.SaveToFile(ExtractFilePath(Application.ExeName) + 'new.xml', dfXML);
  finally
    OldDataSet.Free;
    NewDataSet.Free;
  end;
end;