处理ClientDataset的Delta

5

我遇到了一个与处理 TClientDataSet 的 Delta 相关的代码问题,我已经将它精简为以下测试用例。

我有两个 ClientDataSets,cdsData 和 cdsDelta,都具有 DataSource、DBGrid 和 DBNavigator,还有一个 TTreeView 用于显示 Delta 的 OldValues 和 NewValues。

在 cdsData 的 AfterPost 中,我调用下面的 DisplayDelta 过程。

当我运行应用程序时,我将 csdData 中的一个字段的值从“PrevValue”更改为“UpdatedValue”,并保存。我的问题是 Treeview 中的 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;

嗯。你的树形视图子节点的代码看起来与RecErr.Pas(提供的错误协调表单)中的代码非常相似,所以我不能立即看出为什么那个能工作而你的不能。我依稀记得前Borlander Mark Edington曾在NG上发布过关于这方面的帖子。稍后再说... - MartynA
请查看 provider.pas 和 TPacketDataSet.InitAltRecBuffers 以了解如何处理增量记录。 - Vladimir Ulchenko
1个回答

5

I can reproduce your problem. Try this:

Change

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

现在您应该发现,您得到了预期的OldValueNewValue值。无论如何,在这里我确实得到了。
我承认我有点困惑 - 我一直以为你可以将一个CDS的Delta分配给另一个CDS,并且第二个CDS将包含与Delta相同的字段值(旧值和新值),但显然不是这样。然而,这个结果与Cary Jensen出色的《ClientDataSets》(第6章中的“StatusFilter Versus Delta”)的一部分相吻合,他说:
“…当您使用CDS的Delta加载第二个CDS时,第二个CDS没有更改缓存。”
也许他的意思是,您在第二个CDS中得到的是Delta的快照,而不是历史记录。我想这就是为什么您的cdsDelta返回相同的Field.OldValue和Field.NewValue值的原因。

Delta不是原始数据集。对于每个修改的记录,在Delta数据包中有两行,第一行包含原始字段值,第二行包含修改后的值。 - Vladimir Ulchenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接