Delphi XE5获取 TClientDataSet 的变更明细

在 Delphi XE5 中,要获取 TClientDataSet 的变更明细(包括新增、修改、删除的记录),可以通过其内置的 Delta 属性状态标志 实现。以下是详细步骤和代码示例:


核心方法:使用 Delta 属性

TClientDataSet 内部维护了一个变更日志(Delta),记录所有未提交的更改。通过访问 Delta 属性,可获取完整的变更明细。

步骤 1:获取变更数据集

var
  DeltaCDS: TClientDataSet;
begin
  // 创建临时数据集接收变更信息
  DeltaCDS := TClientDataSet.Create(nil);
  try
    // 将源 ClientDataSet 的变更数据赋给 DeltaCDS
    DeltaCDS.Data := cdsMain.Delta; // cdsMain 是你的主数据集
    if DeltaCDS.IsEmpty then
      ShowMessage('没有变更记录')
    else
      // 遍历变更记录(见下一步骤)
      ...
  finally
    DeltaCDS.Free;
  end;
end;

步骤 2:遍历变更记录并识别状态

每条变更记录都有一个 UpdateStatus 属性,标识其状态(新增、修改、删除)。遍历 DeltaCDS 即可获取明细:

DeltaCDS.First;
while not DeltaCDS.Eof do
begin
  case DeltaCDS.UpdateStatus of
    usInserted: // 新增记录
      begin
        ShowMessage('新增: ID=' + DeltaCDS.FieldByName('ID').AsString);
      end;

    usModified: // 修改记录
      begin
        // 获取修改前和修改后的值
        Field := DeltaCDS.FieldByName('Price');
        ShowMessage(Format('修改: ID=%s, Price (旧值=%.2f, 新值=%.2f)', [
          DeltaCDS.FieldByName('ID').AsString,
          Field.OldValue,       // 修改前的值
          Field.NewValue        // 修改后的值
        ]));
      end;

    usDeleted: // 删除记录
      begin
        ShowMessage('删除: ID=' + DeltaCDS.FieldByName('ID').AsString);
      end;
  end;
  DeltaCDS.Next;
end;

关键属性说明

属性/方法 作用
Delta 返回包含所有变更的 OleVariant,可赋值给另一个 TClientDataSet
UpdateStatus 记录状态:usInserted(新增)、usModified(修改)、usDeleted(删除)
Field.OldValue 获取字段修改前的值(仅 usModified 状态有效)
Field.NewValue 获取字段修改后的值
ChangeCount 返回变更记录的总数量(整数)

完整代码示例

procedure TForm1.GetChangeDetails;
var
  DeltaCDS: TClientDataSet;
  Field: TField;
  Detail: string;
begin
  if cdsMain.ChangeCount = 0 then
  begin
    ShowMessage('没有变更记录');
    Exit;
  end;

  DeltaCDS := TClientDataSet.Create(nil);
  try
    DeltaCDS.Data := cdsMain.Delta; // 加载变更数据
    DeltaCDS.First;

    Memo1.Lines.Clear; // 用 TMemo 显示明细
    Memo1.Lines.Add('===== 变更明细 =====');

    while not DeltaCDS.Eof do
    begin
      Detail := '';
      case DeltaCDS.UpdateStatus of
        usInserted:
          Detail := Format('新增: ID=%s, Name=%s', [
            DeltaCDS.FieldByName('ID').AsString,
            DeltaCDS.FieldByName('Name').AsString
          ]);

        usModified:
          begin
            Field := DeltaCDS.FieldByName('Price');
            Detail := Format('修改: ID=%s, Price 旧值=%.2f → 新值=%.2f', [
              DeltaCDS.FieldByName('ID').AsString,
              Field.OldValue,
              Field.NewValue
            ]);
          end;

        usDeleted:
          Detail := Format('删除: ID=%s', [
            DeltaCDS.FieldByName('ID').AsString
          ]);
      end;

      if Detail <> '' then
        Memo1.Lines.Add(Detail);

      DeltaCDS.Next;
    end;
  finally
    DeltaCDS.Free;
  end;
end;

注意事项

  1. Delta 数据集为只读
    通过 Delta 获取的数据集只能遍历,不能直接修改(会引发异常)。

  2. 清除变更记录
    调用 MergeChangeLogApplyUpdates 后,变更明细会被清空。如需保留变更,应在操作前获取 Delta。

  3. 字段内容不一致

    • 新增记录(usInserted):所有字段均为新值。
    • 修改记录(usModified):通过 OldValueNewValue 对比变化。
    • 删除记录(usDeleted):记录存在但字段值为空,需通过标识确认。
  4. 性能优化
    对大型数据集,在遍历前调用 DisableControls 提高性能,遍历结束后调用 EnableControls


替代方案:直接遍历主数据集

如果不想使用 Delta,可通过遍历主数据集并检查状态获取变更(效率较低):

cdsMain.First;
while not cdsMain.Eof do
begin
  case cdsMain.UpdateStatus of
    usModified: 
      begin
        // 直接访问字段的 OldValue/NewValue
        ShowMessage('修改: ' + cdsMain.FieldByName('Name').OldValue);
      end;
    // ...其他状态处理
  end;
  cdsMain.Next;
end;

通过上述方法,你可以在 Delphi XE5 中完整追踪 TClientDataSet 的所有变更明细。

posted @ 2025-08-05 10:48  我是狂草  阅读(54)  评论(0)    收藏  举报