2010-02-05 74 views
2

我有一個複雜的事務,保存數據庫中多個TClientDataSets的數據。如何將所有TClientDataSet記錄標記爲插入?

其中一個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; 

有沒有一種簡單的方法,只是標記所有記錄作爲插入?

+0

您的解決方案似乎夠簡單。我最後會爲Tmp.Free添加一個嘗試,但那會是關於它的。 – 2010-02-06 08:48:31

回答

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; 
+0

這不起作用。我沒有計算或查找字段。 – dmajkic 2010-02-08 19:47:08

+0

正如我在答案中所說的那樣,如果你離開被黑客入侵的記錄並且BufferCount爲1,這將不起作用。因爲我不知道你對「usInserted」記錄做了什麼,所以很難猜測是否「相信記錄被插入的代碼將不會滿足您的目的。無論如何,我會編輯答案...... – 2010-02-08 22:18:48

+0

將所有記錄設置爲插入後,我執行ApplyUpdates(0)。實際上,我想要的只是爲ClientDataSet中的每一行生成的「INSERT INTO TABLE ...」。 – dmajkic 2010-02-09 12:34:23