реализация стека команд для получения транзакционного поведения - Delphi - PullRequest
0 голосов
/ 08 ноября 2010

Мне нужно создать инструмент для выполнения сложных сценариев для базы данных.

В некоторых случаях я не могу полагаться на поведение транзакций БД, но мне нужно реализовать собственную транзакционную систему.

Подход, который я пробую, заключается в использовании командного шаблона (мой случай более сложный, здесь я приведу упрощенную версию для обсуждения):

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.

1 Ответ

3 голосов
/ 08 ноября 2010

Я не вижу лучшего подхода, чем использование транзакции, поскольку Андрей К. отметил, что ваша реализация НЕ безопасна, поэтому использование StartTransaction, Commit и Rollback ОБЯЗАТЕЛЬНО!

...