来自MemoryTable的FireDAC BatchMove

时间:2015-10-15 17:27:42

标签: delphi firedac

我的传入数据被加载到TFDMemTable(读者)中。作者是TFDQuery。

如果不在目标中,则应插入传入数据,否则更新。匹配基于UUID字段。

我无法正确定义UUID字段是密钥。

这是一个代码示例 - 不起作用。 FBatchMove.Execute失败,因为它找不到任何关键字段。

procedure TSubDB.FindDestRecord(ASender: TObject; var AFound: Boolean);
var
  aSrc: TBytes;
begin
  SetLength(aSrc, 16);
  aSrc := FReader.DataSet.FieldByName('UUID').AsBytes;
  AFound := FWriter.DataSet.Locate('UUID', aSrc, []);
end;

function TSubDB.LoadDB(const aFilename: string): boolean;
var
  FQry: TFDQuery;
  FBatchMove: TFDBatchMove;
  FReader: TFDBatchMoveDataSetReader;
  FWriter: TFDBatchMoveDataSetWriter;
  FMemTable: TFDMemTable;
begin
  FQry := TFDQuery.Create(nil);
  FQry.Connection := dmFB.myDB;
  FQry.FetchOptions.AssignedValues := [evItems];
  FQry.FetchOptions.Items := [fiBlobs, fiDetails];
  FBatchMove := TFDBatchMove.Create(nil);
  FBatchMove.Analyze := [taDelimSep, taHeader, taFields];
  FReader := TFDBatchMoveDataSetReader.Create(FBatchMove);
  FWriter := TFDBatchMoveDataSetWriter.Create(FBatchMove);
  FMemTable := TFDMemTable.Create(nil);
  try
    FMemTable.LoadFromFile(aFileName, sfBinary);
    //Not sure how to make the BatchMove recognize that UUID is the key for OnFindDestRecord
    FMemTable.IndexFieldNames := 'UUID';
    with FMemTable.Indexes.Add do
    begin
      Name :='idxUUID';
      Fields := 'UUID';
      Active := true;
    end;
    FMemTable.IndexName := 'idxUUID';
    FMemTable.IndexesActive := true;
    FMemTable.FieldByName('UUID').ProviderFlags := FMemTable.FieldByName('UUID').ProviderFlags + [pfInKey];
    FReader.DataSet := FMemTable;
    FQry.SQL.Text := 'select * from test';
    FWriter.DataSet := FQry;
    FBatchMove.OnFindDestRecord := FindDestRecord;
    FBatchMove.Mode := dmAppendUpdate;
    //None of the above seems to keep the pfInKey in the UUID field's ProviderFlags
    FBatchMove.Execute;
    FQry.Open;
    FQry.Close;
  finally
    FMemTable.Free;
    FWriter.Free;
    FReader.Free;
    FBatchMove.Free;
    FQry.Free;
  end;
end;

我真的很感激批量移动的一个工作示例(目标有数据,因此批量移动模式是dmAppendUpdate)。

1 个答案:

答案 0 :(得分:1)

这里的关键是作者需要是一个设置了TableName的TFDBatchMoveSQLWriter。这样,目标就定义了主键,然后用它来决定是插入还是更新。

function TSubDB.LoadDB(const aFilename: string): boolean;
var
  FQry: TFDQuery;
  FBatchMove: TFDBatchMove;
  FReader: TFDBatchMoveDataSetReader;
  FWriter: TFDBatchMoveSQLWriter;
  FMemTable: TFDMemTable;
begin
  FQry := TFDQuery.Create(nil);
  FQry.Connection := dmFB.myDB;
  FQry.FetchOptions.AssignedValues := [evItems];
  FQry.FetchOptions.Items := [fiBlobs, fiDetails];
  FBatchMove := TFDBatchMove.Create(nil);
  FBatchMove.Analyze := [taDelimSep, taHeader, taFields];
  FReader := TFDBatchMoveDataSetReader.Create(FBatchMove);
  FWriter := TFDBatchMoveSQLWriter.Create(FBatchMove);
  FMemTable := TFDMemTable.Create(nil);
  try
    FMemTable.LoadFromFile(aFileName, sfBinary);
    FReader.DataSet := FMemTable;
    FQry.SQL.Text := 'select * from test';
    FWriter.Connection := dmFB.myDB;
    FWriter.TableName := 'test';
    FBatchMove.Mode := dmAppendUpdate;
    FBatchMove.Execute;
    FQry.Open;
    FQry.Close;
  finally
    FMemTable.Free;
    FWriter.Free;
    FReader.Free;
    FBatchMove.Free;
    FQry.Free;
  end;
end;