我需要创建一个工具来针对数据库执行复杂的脚本。
出于几个原因,我不能依赖数据库事务行为,但我需要实现自己的事务系统。
我正在尝试的方法是借助命令模式(我的情况比较复杂,这里我放一个简化版本供讨论):
type
IMyCommand = interface(IInterface)
procedure Execute();
procedure Undo();
end;
type
TSQLCommand = class (TInterfacedObject, IMyCommand)
private
FDBConnection: TDBConnection;
FDBQuery: TDBQuery;
FExecuteSQL: string;
FUndoSQL: string;
FExecuted: boolean; // set to True as the command has been executed
public
procedure Execute;
procedure Undo;
procedure Prepare(aExecuteSQL, aUndoSQL: string);
constructor Create(aDBConnection: TDBConnection);
destructor Destroy; override;
end;
我创建了一组动作,对于每个动作,我都会传递一个“执行”和“撤消”的 sql 语句,示例:
对 Prepare 的调用可能是:
Prepare('INSERT INTO TESTTABLE (ID, DATA) VALUES (15, 'Hello')',// aExecuteSQL
'DELETE FROM TESTTABLE WHERE ID = 15'); //aUndoSQL
所以不知何故我做了非常小的改变(比如插入一个简单的行,更新一个行,......),对于每一个改变,“撤消”都是非常明显的。
我将准备一堆命令对象(可能使用 TObjectStack 集合),并一次调用一个命令的 Execute 方法,并在执行一个命令时将 FExecuted 设置为 True,并将组件保存到磁盘。
所以我想做的是运行所有脚本,但我想管理出现问题的情况。
如果出现问题,我想执行从最后到第一个调用 Undo 方法的所有命令。当然,在这样做之前,我需要能够从磁盘恢复组件(如果故障是硬件故障,如果故障是另一个原因,我已经在内存中拥有堆栈,我可以轻松地调用撤消一个命令时间)。
注意:我不能依赖数据库事务行为的主要原因是我还需要插入大 blob,每个 blob 都是从 Internet 下载然后插入的,所以我不能永远打开事务,因为我想提交每个对分贝的小改动。我对 blob 所做的是下载一个,插入它,下载下一个,插入它,...
所以我的问题是:你能建议一种方法来持久存储我的对象吗?我有 Delphi 2009,所以一个选择是制作一个 TInterdacedPersistent 并将组件保存到流然后保存到文件,无论如何,这样我会有很多文件,有额外的复杂性,而我更喜欢单个文件。你能建议吗?
编辑:我意识到 TObjectStack 在 Delphi 2009 中有错误(Pop 没有返回正确的类型),所以 TObjectStack 也可以这样做。