如何将所有TClientDataSet记录标记为已插入? [英] How to mark all TClientDataSet records as Inserted?

查看:153
本文介绍了如何将所有TClientDataSet记录标记为已插入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个复杂的事务,它从数据库中的多个TClientDataSet中保存数据。

I have a complex transaction that saves data from multiple TClientDataSets in database.

其中一个ClientDataSet总是将数据追加到底层表中,例如。不管现有记录来自何处,都将生成INSERT语句。

One of those ClientDataSets always append data to underlaying table, eg. generate INSERT statements, regardless of where existing records came from.

我现在强制插入:

// 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;

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

Is there a simpler way to just mark all records as inserted?

推荐答案

有人希望……。这样(至少在没有计算字段的情况下才行);

One would hope sth. like this would work (at least when there are no calculated fields);

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 重新设置记录属性。我猜想这使这种骇人听闻的方法变得毫无用处。

Well, it works, but as long as no data is re-retrieved. That is, TCustomClientDataSet.GetRecord re-sets the record attributes. This renders the hacky approach pretty useless I guess.

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

Maybe one could try binding a data-aware control and see if setting the BufferCount of the DataLink of the DataSource would help. Or, try overriding GetRecord in a descendant ClientDataSet. But I doubt it is worth the effort.

可以在 AfterScroll事件中 hack 记录属性。例如,这将有助于代码测试UpdateStatus以返回 usInserted。

The record attribute can be hacked in an "AfterScroll" event. This would help, for instance, code testing the UpdateStatus to return "usInserted".

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

测试是否插入了所有记录

Test if all the records are inserted

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来检索总是插入



A new TClientDataSet can be derived to retrieve always "inserted" records.

(类型声明在包含ClientDataSet的表单/数据块之前之前

(The type declaration goes before the form/datamoule containing the ClientDataSet)

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。

Now for all records, UpdateStatus will return "usInserted".

编辑

我终于明白,目标是为所有记录生成插入SQL。我们不会通过修改数据集的记录属性来实现此目的,ApplyUpdates仅考虑增量,而我们可能没有增量。可能有不同的方法可以实现此目的,下面的示例假定DataSet有一个Provider,并且我们可以在其上放置事件处理程序。

I finally understood that the aim is to generate insert SQLs for all records. We won't achieve this by modifying records' attributes of the DataSet, ApplyUpdates takes only the "Delta" into consideration and we possibly have no Delta. There might be different ways to achieve this, the below example assumes the DataSet has a Provider and we are able to put an event handler on it.

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;

这篇关于如何将所有TClientDataSet记录标记为已插入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆