Мне нужно создать инструмент для выполнения сложных сценариев для базы данных.
В некоторых случаях я не могу полагаться на поведение транзакций БД, но мне нужно реализовать собственную транзакционную систему.
Подход, который я пробую, заключается в использовании командного шаблона (мой случай более сложный, здесь я приведу упрощенную версию для обсуждения):
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-операторы «Execute» и «Undo», примеры:
Вызов может быть следующим:
Prepare('INSERT INTO TESTTABLE (ID, DATA) VALUES (15, 'Hello')',// aExecuteSQL
'DELETE FROM TESTTABLE WHERE ID = 15'); //aUndoSQL
, поэтому как-то я делаю очень небольшие изменения (например, вставляю одинпростая строка, обновление одной строки, ...), для каждого изменения «отмена» очень очевидна.
Я подготовлю стек объектов команд (используя, вероятно, коллекцию TObjectStack) и вызову ExecuteПри выполнении одной команды за раз, и после ее выполнения я установлю для FExecuted значение True и сохраню компонент на диск.
Итак, мне нужно запустить все сценарии, но яЯ хочу управлять случаями, когда что-то идет не так.
Если что-то идет не так, я хотел бы выполнить все команды от последней до первого вызова метода Undo.Конечно, прежде чем сделать это, я должен иметь возможность восстановить с диска компоненты (в случае, если сбой является аппаратным сбоем, если сбой является еще одной причиной, у меня уже есть стек в памяти, и я могу легко вызвать команду отмены однойвремя).
Примечание. Основная причина, по которой я не могу полагаться на транзакционное поведение БД, заключается в том, что мне нужно вставить также большие большие двоичные объекты, и каждый большой двоичный объект загружается из Интернета, а затем вставляется, поэтому я не могу выйти из транзакции.открыт навсегда, потому что я хочу совершить каждое небольшое изменение в БД.Что я делаю с BLOB-объектами, так это скачиваю одну, вставляю ее, скачиваю затем, вставляю, ...
Итак, мой вопрос: не могли бы вы предложить способ сохранения моих объектов на диске?У меня Delphi 2009, поэтому один из вариантов - создать TInterdacedPersistent и сохранить компонент в поток, а затем в файл. В любом случае, таким образом, у меня будет много файлов с дополнительными сложностями, хотя я бы предпочел один файл.Не могли бы вы предложить?
Редактировать: я понял, что TObjectStack содержит ошибки в Delphi 2009 (Pop не возвращает правильный тип), поэтому то же самое можно сделать с TObjectStack.