2016-08-26 11 views
4

TClientDataSetの デルタを処理するはずのコードで問題が発生しましたが、これは次のテストケースに沸かせました。ClientDataSetのデルタの処理

私は、DataSource、DBGrid 、DBNavigator、DeltaのOld-とNewValuesを表示するためのTTreeViewの2つのClientDataSet cdsDataとcdsDeltaを持っています。

cdsDatas AfterPostでは、以下のDisplayDeltaプロシージャを呼び出します。

私はアプリを実行すると、csdDataの1フィールドの値を変更して、 から 'PrevValue'を 'UpdatedValue'に変更して保存します。私の問題は、ツリービューの OldValueとNewValueノードの両方が 'UpdatedValue'を表示し、 'PrevValue'の記号がないことです。だから、どうすればOldValueを正しく取得できますか?

procedure TDeltaTestForm.DisplayDelta; 
var 
    Delta : OleVariant; 
begin 
    Delta := cdsData.Delta; 
    if not VarIsClear(Delta) then begin 
    cdsDelta.Data := Delta; 
    end; 
    if cdsData.Modified then 
    Caption := 'modified' 
    else 
    Caption := ''; 
    Caption := Caption + '/' + IntToStr(cdsData.ChangeCount); 
    BuildDeltaTree; 
end; 

procedure TDeltaTestForm.BuildDeltaTree; 
var 
    NewNode, 
    ChildNode : TTreeNode; 
    i, 
    ID : Integer; 
    Field : TField; 
    Value : String; 

    function ChildValue(ALabel : String; FieldValue : Variant) : String; 
    begin 
    Result := ALabel; 
    if VarIsClear(FieldValue) then 
     Result := Result + '(empty)' 
    else 
     if VarIsNull(FieldValue) then 
     Result := Result + '(null)' 
     else 
     Result := Result + VarToStr(FieldValue); 
    end; 
begin 
    { Find the current row in the delta dataset } 

    ID := cdsData.FieldByName('ID').AsInteger; 
    if not cdsDelta.Locate('ID', ID, []) then 
    raise Exception.CreateFmt('ID: %d not found in Delta', [ID]); 

    TreeView1.Items.BeginUpdate; 
    try 
    Treeview1.Items.Clear; 
    for i:= 0 to cdsDelta.FieldCount - 1 do begin 
     Field := cdsDelta.Fields[i]; 
     NewNode := TreeView1.Items.AddChild(Nil, Field.FieldName); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('Old: ', Field.OldValue)); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('New: ', Field.NewValue)); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('Cur: ', Field.CurValue)); 
    end; 
    TreeView1.FullExpand; 
    finally 
    TreeView1.Items.EndUpdate; 
    end; 
end; 
+0

Hmm。あなたのツリービューの子ノードのコードは、RecErr.Pas(提供されているエラー調整フォーム)のコードと非常によく似ています。私はボランダール元Mark EdingtonのNG投稿を曖昧に覚えています。後で... – MartynA

+0

デルタレコードを処理する方法を知るためにprovider.pasとTPacketDataSet.InitAltRecBuffersを参照してください – vavan

答えて

4

問題を再現できます。これを試してください:あなたは今、あなたが期待しているNewValueOldValueの値を取得していることを見つける必要があります

for i:= 0 to cdsDelta.FieldCount - 1 do begin 
    Field := cdsDelta.Fields[i]; 

for i:= 0 to cdsData.FieldCount - 1 do begin 
    Field := cdsData.Fields[i]; 

変更。とにかく、私はここでやっています。

私はこれに少し戸惑っています - 私はいつもあなたが1つのCDSのデルタを別のCDSに割り当てることができ、2つ目は同じデルタと同じフィールド値(古いものと新しいもの)明らかにそうではない。しかし、この結果は、Cary Jensenの優れた「ClientDataSets」(第6章の「StatusFilterとDelta」の項を参照)でチャーミングします。

"... CDSのDeltaで第2のCDSをロードすると、 CDSには変更キャッシュがありません。

おそらく、彼が2番目のもので終わるのは、デルタの歴史ではなく、スナップショットです。私はあなたのcdsDeltaがField.OldValueとField.NewValueに同じ値を返すのはそうだと思います。

+0

デルタは元のデータセットではありません。変更されたレコードごとに、元のフィールド値を含む2つの行と、変更された値を含む2つの行がデルタパケットにあります – vavan