2

I try to change the field name of FDMemTable1field1 which is 'field1' to 'field3'. There is no code and all is done in design-time.

TForm1 = class(TForm)
  DBGrid1: TDBGrid;
  DataSource1: TDataSource;
  FDMemTable1: TFDMemTable;
  FDMemTable1field1: TStringField;
  FDMemTable1field2: TStringField;

When a file is loaded via FDMemTable1 pop-up menu in design window DBGrid1 shows data well. Changing 'field1' to 'field3' in Object Inspector makes FDMemTable1.Active 'false' and all cells of DBGrid1 clear.

Switching FDMemTable1.Active 'true' shows only DBGrid1 title 'field3' and 'field2' not data cells.

At last loading the same file fires an error Field 'field3' not found. Even if I change the name after the deactivation of FDMemTable1 the result is same.

Is changing a field name in design-time possible? Should I copy the whole 'field1' to 'field3' and delete the former in run-time?

SHIN JaeGuk
  • 494
  • 1
  • 5
  • 14
  • Just an idea: The file you load has embedded field names (Field1 and Field2). If the TFDMemTable try to load that file after you renamed Field1 to Field3, you get the error because field defined in the component doesn't match fields saved in the file. – fpiette May 06 '21 at 14:40
  • @fpiette Absolutely it does. I think the change should be implemented while the table is loaded like the implementation in SQL. But the try unloads the table in design-time and emits an error ```FDMemTable1: Cannot perform this operation on an open dataset.``` in run-time. – SHIN JaeGuk May 06 '21 at 15:39
  • 1
    Changing an FDMemTable FieldName at design-time is certainly possible, but not while the data is saved to disk because the FieldName has to be consistent with the saved metadata. Why not just use the correct field name in the first place? – MartynA May 06 '21 at 16:05
  • 1
    Btw, probably the least painful way of doing what you way would be to save the data to XML, change the FieldName in the XML and then reload it into the FDMemtable. – MartynA May 06 '21 at 16:12

1 Answers1

2

I think that a problem with what you want is that afaik you can't rename a field in an FDMemTable while it has data stored in it, because the field name is amongst the metadata stored in the saved data.

That said, here's a minimal example of renaming an FDMemTable field without having to discard the data stored in it. Basically, it writes the table's data out in XML format, changes the field name (in this case 'FieldA') to something different ('FieldB') and reloads the data from the changed XML file.

uses [...] FireDAC.Stan.StorageXML;

type
  TForm1 = class(TForm)
    FDMemTable1: TFDMemTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Button1: TButton;
    FDStanStorageXMLLink1: TFDStanStorageXMLLink;
    procedure FormCreate(Sender: TObject);
  public
  end;

[...]

procedure TForm1.Button1Click(Sender: TObject);
var
  AFileName : String;
  TL : TStringList;
  S : String;
begin
  AFileName := 'C:\Temp\XMLData.XML';

  FDMemTable1.SaveToFile(AFileName, sfXML);
  TL := TStringList.Create;
  try
    TL.LoadFromFile(AFileName);
    FDMemTable1.Close;

    TL.Text := StringReplace(TL.Text, 'FieldA', 'FieldB', [rfReplaceAll]);
    TL.SaveToFile(AFileName);

    DBGrid1.Columns.Clear;
    FDMemTable1.FieldDefs.Clear;
    FDMemTable1.Fields.Clear;
    FDMemTable1.LoadFromFile(AFileName, sfXML);
  finally
    TL.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Link : TFDStanStorageXMLLink;  //  This is needed to reload the data in XML format
  AField : TField;
begin

  Link := TFDStanStorageXMLLink.Create(Self);

  AField := TIntegerField.Create(Self);
  AField.FieldName := 'ID';
  AField.DataSet := FDMemTable1;

  AField := TStringField.Create(Self);
  AField.FieldName := 'FieldA';
  AField.Size := 32;
  AField.DataSet := FDMemTable1;

  FDMemTable1.CreateDataSet;

  FDMemTable1.InsertRecord([1, 'One']);
  FDMemTable1.InsertRecord([2, 'Two']);
end;

Obviously, if you didn't want to write the data to the filesystem, you could use a temporary stream and the FDMemTable's SaveToStream and LoadFromStream.

MartynA
  • 30,454
  • 4
  • 32
  • 73