代码之家  ›  专栏  ›  技术社区  ›  dmajkic

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

  •  2
  • dmajkic  · 技术社区  · 15 年前

    我有一个复杂的事务,它在数据库中保存来自多个tclientdataset的数据。

    其中一个客户机数据集总是将数据附加到底层表,例如生成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 回复  |  直到 15 年前
        1
  •  1
  •   Sertac Akyuz    15 年前

    人们希望这样的事情能奏效(至少在没有计算字段的情况下);

    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 重新设置记录属性。我想,这使得黑客方法变得相当无用。

    也许可以尝试绑定一个数据感知控件,看看设置数据源的数据链接的bufferCount是否有帮助。或者,尝试重写子代clientdataset中的getrecord。但我怀疑这值得付出努力。

    [编辑]

    记录属性可以是 在“AfterScroll”事件中。例如,这将有助于对updateStatus进行代码测试,以返回“usineserted”。

    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来检索始终“插入”的记录。

    (类型声明为 之前 包含客户端数据集的窗体/数据模型)

    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将返回“usinested”。

    编辑

    我最终理解了目标是为所有记录生成insert sqls。我们不能通过修改数据集记录的属性来实现这一点,ApplyUpdates只考虑“delta”,我们可能没有delta。可能有不同的方法来实现这一点,下面的示例假设数据集有一个提供者,并且我们能够在它上面放置一个事件处理程序。

    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;