Поделиться через


Обновление модели с помощью транзакций

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

Всякий раз, когда код программы изменяет, добавляет или удаляет любой элемент в Магазине в visual Studio Visual Studio Sdk, он должен сделать это внутри транзакции. При изменении должен быть активный экземпляр, связанный Transaction с Магазином. Это относится ко всем элементам модели, связям, фигурам, схемам и их свойствам.

Механизм транзакций помогает избежать несогласованных состояний. Если во время транзакции возникает ошибка, все изменения откатываются. Если пользователь выполняет команду undo, каждая последняя транзакция рассматривается как один шаг. Пользователь не может отменить части недавнего изменения, если только вы явно не помещаете их в отдельные транзакции.

Открытие транзакции

Самый удобный способ управления транзакцией — это инструкция, using заключенная в try...catch оператор:

Store store; ...
try
{
  using (Transaction transaction =
    store.TransactionManager.BeginTransaction("update model"))
    // Outermost transaction must always have a name.
  {
    // Make several changes in Store:
    Person p = new Person(store);
    p.FamilyTreeModel = familyTree;
    p.Name = "Edward VI";
    // end of changes to Store

    transaction.Commit(); // Don't forget this!
  } // transaction disposed here
}
catch (Exception ex)
{
  // If an exception occurs, the Store will be
  // rolled back to its previous state.
}

Если исключение, препятствующее окончательному Commit() выполнению изменений, магазин будет сброшен на предыдущее состояние. Это помогает убедиться, что ошибки не покидают модель в несогласованном состоянии.

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

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

Откат транзакции

Чтобы убедиться, что Магазин остается в состоянии или отменить изменения до транзакции, можно использовать любую из следующих тактик:

  1. Вызовите исключение, которое не поймано внутри область транзакции.

  2. Явным образом откат транзакции:

    this.Store.TransactionManager.CurrentTransaction.Rollback();
    

Транзакции не влияют на объекты, не относящиеся к хранилищу

Транзакции управляют только состоянием Магазина. Они не могут отменить частичные изменения, внесенные во внешние элементы, такие как файлы, базы данных или объекты, объявленные обычными типами за пределами определения DSL.

Если исключение может оставить такое изменение несогласованным с Магазином, вы должны иметь дело с этой возможностью в обработчике исключений. Один из способов убедиться, что внешние ресурсы остаются синхронизированными с объектами Store, заключается в подключении каждого внешнего объекта к элементу в хранилище с помощью обработчиков событий. Дополнительные сведения см. в разделе Обработчики событий, распространяющие изменения за пределами модели.

Правила срабатывает в конце транзакции

В конце транзакции перед удалением транзакции будут запущены правила, присоединенные к элементам в хранилище. Каждое правило — это метод, применяемый к измененным элементу модели. Например, существуют правила "исправления", которые обновляют состояние фигуры при изменении его элемента модели и создают фигуру при создании элемента модели. Нет указанного порядка стрельбы. Изменение, внесенное правилом, может запустить другое правило.

Вы можете определить собственные правила. Дополнительные сведения о правилах см. в разделе "Реагирование на изменения" и "Распространение изменений".

Правила не выполняются после отмены, повторного выполнения или команды отката.

Контекст транзакции

Каждая транзакция содержит словарь, в котором можно хранить любые нужные сведения:

store.TransactionManager

.CurrentTransaction.TopLevelTransaction

.Context.Add(aKey, aValue);

Это особенно полезно для передачи информации между правилами.

Состояние транзакции

В некоторых случаях необходимо избежать распространения изменений, если изменение вызвано отменой или повтором транзакции. Это может произойти, например, если вы напишете обработчик значений свойства, который может обновить другое значение в Магазине. Так как операция отмены сбрасывает все значения в Хранилище до предыдущих состояний, не требуется вычислять обновленные значения. Используйте следующий код:

if (!this.Store.InUndoRedoOrRollback) {...}

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

if (!this.Store.InSerializationTransaction) {...}