是否可以将对从 TFDQuery 克隆的 TFDMemTable 所做的更改发送回数据库?

Can changes made to a TFDMemTable cloned from a TFDQuery be sent back to the database?

With Delphi 10 Seattle 我正在尝试用 TFDMemTable 克隆 TFDQuery 并将 TFDMemTable 中所做的更改保存到数据库中。

memtable 更改出现在查询中,但没有一直到数据库。如果我直接修改查询中的值,它们会保存在数据库中。

var
  query : TFDQuery;
  memtable : TFDMemTable;
begin
  { run TFDQuery }
  query := TFDQuery.Create(nil);
  query.SQL.Text := 'select * from employee';
  query.Open;

  { clone query into memtable }
  memtable := TFDMemTable.Create(nil);
  memtable.CloneCursor(query);

  { go to the same record in query and memtable }
  memtable.First;
  query.First;
  Assert(memtable.Fields[0].Value = query.Fields[0].Value);

  { edit the record in the memtable from ABC to XYZ }
  Assert(memtable['SomeField'] = 'ABC');
  memtable.Edit;
  memtable['SomeField'] := 'XYZ';
  memtable.Post;

  { verify record also changed in query }
  Assert(query['SomeField'] = 'XYZ');

  { has the change gone through to the database? }
  query.Close;
  query.Open;
  query.First;
  Assert(query['SomeField'] = 'XYZ');  // assertion fails, value is still ABC

有趣的问题。我试图通过使用 MergeDataSet.

来解决这个问题

然而,我想知道我是不是想把它做太多。 令我惊讶的是,我找到了以下作品,并且在 FDMemTable 中所做的更改被保存回数据库(MS Sql Server 2014 使用作者 table 在 MS pubs 数据库中,Delphi 西雅图):

procedure TForm1.btnCopyToMemTableClick(Sender: TObject);
begin
  FDMemTable1.CloneCursor(FDQuery1);
end;

procedure TForm1.btnSaveBackClick(Sender: TObject);
var
  Errors : Integer;
begin
  Errors := FDQuery1.ApplyUpdates;
  FDQuery1.Close;
  //  need to close FDMemTable1 before re-opening FDQuery1, otherwise the
  //  call to FDQuery1 provokes a complaint about a duplicated column.
  FDMemTable1.Close;

  FDQuery1.Open;
  FDMemTable1.CloneCursor(FDQuery1);
end;

由此看来,您的代码似乎在 query 关闭之前缺少 query.ApplyUpdates(0),并且在尝试 re-open [=14] 之前缺少对 memtable.close 的调用=] 以避免代码中指出的错误。

所以在这种情况下,KISS 似乎适用,但我很想知道是否有一种方法可以使用 MergeDataSet.

获得相同的结果

顺便说一句,以下是您的代码的一个小变体,以适应我的测试平台:

var
  query : TFDQuery;
  memtable : TFDMemTable;
begin
  //  Using the MS pubs demo database
  query := FDQuery1;
  query.SQL.Text := 'select * from authors';
  query.CachedUpdates := True;
  query.Open;

  { clone query into memtable }
  memtable := FDMemTable1;
  memtable.CloneCursor(query);

  { go to the same record in query and memtable }
  memtable.First;
  query.First;
  Assert(memtable.Fields[0].Value = query.Fields[0].Value);

  { edit the record in the memtable from ABC to XYZ }
  //Assert(memtable[''] = 'ABC');
  memtable.Edit;
  memtable['Phone'] := '666';
  memtable.Post;

  { verify record also changed in query }
  Assert(query['Phone'] = '666');

  //  Added
  query.ApplyUpdates(0);
  { has the change gone through to the database? }
  query.Close;

  //  Added
  //  need to close memtable before re-opening query, otherwise the
  //  call to query provokes a complaint about a duplicated column.
  memtable.Close;

  query.Open;
  query.First;
  Assert(query['Phone'] = '666');  // assertion succeeds