TFDMemTable SavePoint提交后无法回滚变更的问题求助
TFDMemTable SavePoint 正确用法及问题解析
问题根源
TFDMemTable的SavePoint并非针对内存表的最终数据状态,而是仅对开启缓存更新(CachedUpdates=True)后的未提交缓存修改生效。
当CachedUpdates=False(默认)时,Post操作会直接将修改写入内存表的物理存储,此时SavePoint无法回滚已经持久化的修改——因为它只跟踪缓存中的更新队列,管不到已经落地的内存数据。
即使你开启了CachedUpdates=True,如果修改已经通过ApplyUpdates提交到内存表,SavePoint同样无法回滚这些已提交的内容。
正确用法步骤
- 必须提前开启缓存更新:在调用
Open前设置CachedUpdates := True,这是SavePoint生效的前提。 - SavePoint跟踪缓存修改:所有
Append/Edit后的Post操作,只是把修改暂存到缓存队列,并未真正写入内存表的持久存储。 - 回滚到指定保存点:设置
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
相关产品推荐
相关产品推荐

