You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TFDMemTable SavePoint提交后无法回滚变更的问题求助

TFDMemTable SavePoint 正确用法及问题解析

问题根源

TFDMemTable的SavePoint并非针对内存表的最终数据状态,而是仅对开启缓存更新(CachedUpdates=True)后的未提交缓存修改生效。

当CachedUpdates=False(默认)时,Post操作会直接将修改写入内存表的物理存储,此时SavePoint无法回滚已经持久化的修改——因为它只跟踪缓存中的更新队列,管不到已经落地的内存数据。

即使你开启了CachedUpdates=True,如果修改已经通过ApplyUpdates提交到内存表,SavePoint同样无法回滚这些已提交的内容。

正确用法步骤

  1. 必须提前开启缓存更新:在调用Open前设置CachedUpdates := True,这是SavePoint生效的前提。
  2. SavePoint跟踪缓存修改:所有Append/Edit后的Post操作,只是把修改暂存到缓存队列,并未真正写入内存表的持久存储。
  3. 回滚到指定保存点:设置SavePoint为之前记录的值,会撤销缓存队列中保存点之后的所有修改,内存表数据会自动恢复到保存点状态。

修正后的测试代码

var 
  mem: TFDMemTable;
  SVPoint: Integer;
begin
  mem := TFDMemTable.Create(Self);
  try
    with mem.FieldDefs.AddFieldDef do
    begin
      Name := 'name';
      DataType := ftString;
      Size := 50;
    end;
    mem.CachedUpdates := True; // 务必在Open前设置
    mem.Open;

    mem.Append;
    mem.FieldByName('name').AsString := 'Test';
    mem.Post; // 修改存入缓存,未提交到内存表
    ShowMessage(mem.FieldByName('name').AsString); // 输出Test

    SVPoint := mem.SavePoint; // 记录当前缓存状态

    mem.Edit;
    mem.FieldByName('name').AsString := 'Test2';
    mem.Post; // 新修改加入缓存
    ShowMessage(mem.FieldByName('name').AsString); // 输出Test2

    mem.SavePoint := SVPoint; // 回滚到保存点,撤销Test2的修改
    ShowMessage(mem.FieldByName('name').AsString); // 输出Test
  finally
    mem.Free;
  end;
end;

额外说明

  • 如果需要一次性回滚所有未提交的缓存修改,直接调用CancelUpdates即可,无需使用SavePoint。
  • SavePoint适合多步骤的缓存修改场景,允许你回滚到某个中间状态,而非全部撤销。

内容的提问来源于stack exchange,提问作者Bruno Kinast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 00:09:22