如何将所有TClientDataSet记录标记为已插入?

时间:2010-02-05 20:00:49

标签: delphi dbexpress

我有一个复杂的事务,可以保存数据库中多个TClientDataSets的数据。

其中一个ClientDataSets总是将数据附加到底层表,例如。生成INSERT语句,无论现有记录来自何处。

我现在正在强制插入:

// Create temp table, assign all target data, 
// Empty target table, append data from temp

Tmp := TClientDataSet.Create; 
Tmp.Data := Table.Data; 

Table.MergeChangeLog; 
Table.EmptyDataSet;

Tmp.First; 
// Append all records 
While not Tmp.Eof do
begin
  Table.Append;  
  for i := 0 to Table.FieldCount - 1 do
    Table.Fields[i].Value := Tmp.Fields[i].Value 
  Table.Post; 

  Tmp.Next;
end;

Tmp.Free;

是否有更简单的方法将所有记录标记为已插入?

1 个答案:

答案 0 :(得分:1)

有人希望......这样会起作用(至少在没有计算字段时);

uses
  dsintf;

[..]
procedure TForm1.Button1Click(Sender: TObject);
begin
  ClientDataSet1.First;
  while not ClientDataSet1.Eof do begin
    PRecInfo(ClientDataSet1.ActiveBuffer +
        ClientDataSet1.RecordSize).Attribute := dsRecNew;
    ClientDataSet1.Next;
  end;
end;

嗯,它有效,但只要没有重新检索数据。也就是说,TCustomClientDataSet.GetRecord重新设置记录属性。这使得hacky方法在我猜中毫无用处。

也许可以尝试绑定数据感知控件,看看设置DataSource的DataLink的BufferCount是否有帮助。或者,尝试在后代ClientDataSet中覆盖GetRecord。但我怀疑这是值得的。

<强> [编辑]

在“AfterScroll”事件中,记录属性可以黑客攻击。例如,这将有助于对UpdateStatus进行代码测试以返回“usInserted”。

procedure TForm1.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
  PRecInfo(DataSet.ActiveBuffer + DataSet.RecordSize).Attribute := dsRecNew;
end;

测试是否插入了所有记录

procedure TForm1.Button1Click(Sender: TObject);
begin
  ClientDataSet1.First;
  while not ClientDataSet1.Eof do begin
    if not (ClientDataSet1.UpdateStatus = usInserted) then
      raise Exception.Create('The record is not inserted');
    ClientDataSet1.Next;
  end;
end;


<小时/> 可以派生新的TClientDataSet来检索始终“插入”的记录。

(类型声明之前包含ClientDataSet的表单/ datamoule)

type
  TClientDataset = class(dbclient.TClientDataSet)
    function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean):
        TGetResult; override;
  end;
[..]
implementation

function TClientDataset.GetRecord(Buffer: PChar; GetMode: TGetMode;
  DoCheck: Boolean): TGetResult;
begin
  Result := inherited GetRecord(Buffer, GetMode, DoCheck);
  if Result = grOk then
    PRecInfo(Buffer + RecordSize).Attribute := dsRecNew;
end;

现在对于所有记录,UpdateStatus将返回“usInserted”。

修改

我终于明白,目的是为所有记录生成插入SQL。我们不会通过修改DataSet的记录属性来实现这一点,ApplyUpdates只考虑“Delta”而我们可能没有Delta。可能有不同的方法来实现这一点,下面的示例假设DataSet有一个Provider,我们可以在其上放置一个事件处理程序。

type
  TForm1 = class(TForm)
    [..]
  private
    procedure DeltaAfterScroll(DataSet: TDataSet);
    [..]

implementation

procedure TForm1.DeltaAfterScroll(DataSet: TDataSet);
begin
// The UpdateTree of the Resolver of the Provider will visit each 
// record to get the UpdateStatus
  PRecInfo(DataSet.ActiveBuffer + DataSet.RecordSize).Attribute := dsRecNew;
end;


type
  TAccessCCDS = class(TCustomClientDataSet);

procedure TForm1.Button1Click(Sender: TObject);
var
  Count: Integer;
begin
  ClientDataSet1.MergeChangeLog;
// Since there's no "Delta", ApplyUpdates will return immediately.
// Hence, we'll force an update by calling DoApplyUpdates, bypassing the
// ChangeCount test, and update with the "Data".
// Reconcilation is left out for simplicity.
  TAccessCCDS(ClientDataSet1).DoApplyUpdates(ClientDataSet1.Data, 0, Count);
end;

procedure TForm1.DataSetProvider1UpdateData(Sender: TObject;
  DataSet: TCustomClientDataSet);
begin
// Will be called once when ApplyUpdates is called.
  TAccessCCDS(DataSet).AfterScroll := DeltaAfterScroll;
end;