I've been having a problem with some code which is supposed to process a TClientDataSet's Delta, which I've boiled down to the following test case.
I have two ClientDataSets, cdsData and cdsDelta, both with a DataSource, DBGrid and DBNavigator, and a TTreeView for displaying the Delta's Old- and NewValues.
In cdsDatas AfterPost, I call the DisplayDelta procedure below.
When I run the app, I change and save the value of one field in csdData from, say, 'PrevValue' to 'UpdatedValue'. My problem is that both the OldValue and NewValue nodes in the Treeview display 'UpdatedValue' and there is no sign of 'PrevValue'. So, how do I get the OldValue correctly?
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;
I can reproduce your problem. Try this:
Change
for i:= 0 to cdsDelta.FieldCount - 1 do begin
Field := cdsDelta.Fields[i];
to
for i:= 0 to cdsData.FieldCount - 1 do begin
Field := cdsData.Fields[i];
You should now find that you get the values for OldValue
and NewValue
you're expecting. At any rate, I do here.
I confess I'm somewhat puzzled by this - I'd always assumed that you could assign the Delta of one CDS to another and the second one would contain the same field values (Old and New) as the Delta, but evidently not. However, this result chimes with a section of Cary Jensen's excellent "ClientDataSets" ("StatusFilter Versus Delta" in Chapter 6) where he says:
" ... when you load a second CDS with a CDS's Delta, the second CDS does not have a change cache."
Maybe what he means is that what you end up with in the second one is a snapshot of the Delta, not the history of it. I guess that's why your cdsDelta returns the same values in Field.OldValue and Field.NewValue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With