事务可确保对存储所做的更改被视为一个整体。 可将分组的更改提交或回滚为单个单元。
每当程序代码修改、添加或删除 Visual Studio 可视化和建模 SDK 应用商店中的任何元素时,它都必须在事务中执行此作。 发生更改时,必须有一个与应用商店关联的活动实例 Transaction 。 这适用于所有模型元素、关系、形状、关系图及其属性。
事务机制有助于避免状态不一致。 如果在事务期间发生错误,则会回滚所有更改。 如果用户执行撤消命令,则每个最近的事务被视为单个步骤。 用户无法撤销最近更改的部分,除非明确地将这些更改放入单独的事务中。
打开事务
管理事务的最方便方法是将 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 事务释放之前对其进行处理。 如果发生未在事务中捕获的异常,应用商店将在更改之前重置为其状态。
回滚事务
若要确保商店保持或恢复到事务之前的状态,可以采用以下任意一种策略:
引发在事务范围内未捕获的异常。
显式回滚该事务:
this.Store.TransactionManager.CurrentTransaction.Rollback();
事务不会影响非存储对象
事务仅控制应用商店的状态。 它们无法撤消对外部项目(例如文件、数据库或在 DSL 定义之外用普通类型声明的对象)进行的部分更改。
如果异常可能会使此类更改与应用商店不一致,则应在异常处理程序中处理这种可能性。 确保外部资源与 Store 对象保持同步的一种方法是使用事件处理程序将每个外部对象与店内元素耦合。 有关详细信息,请参阅 事件处理程序在模型外传播更改。
事务结束时触发的规则
在事务结束时,在事务被处理之前,附加到存储中元素的规则将被触发。 每个规则都是应用于已更改的模型元素的方法。 例如,有一些“修复”规则会在形状的模型元素发生更改时更新其状态,并在创建模型元素时创建形状。 没有指定的触发顺序。 一个规则所做的更改可能会触发另一个规则。
可以定义自己的规则。 有关规则的详细信息,请参阅 响应和传播更改。
在撤消、重做或回滚命令之后,规则不会触发。
事务上下文
每个事务都有一个字典,可在其中存储所需的任何信息:
store.TransactionManager
.CurrentTransaction.TopLevelTransaction
.Context.Add(aKey, aValue);
这对于在规则之间传输信息特别有用。
事务状态
在某些情况下,如果更改是由撤消或重做事务引起的,则需要避免传播更改。 例如,如果编写了可以更新应用商店中另一个值的属性值处理程序,则可能会发生这种情况。 由于撤消作会将应用商店中的所有值重置为以前的状态,因此无需计算更新的值。 请使用此代码:
if (!this.Store.InUndoRedoOrRollback) {...}
当商店最初从文件加载时,规则可以触发。 若要避免响应这些更改,请使用:
if (!this.Store.InSerializationTransaction) {...}