共用方式為


使用交易來更新模型

交易可確保對資料庫所做的變更被視為一個整體。 分組的變更可以確定或回復為單一單元。

每當您的程式代碼修改、新增或刪除 Visual Studio 視覺化和建模 SDK 中的市集中的任何元素時,它都必須在交易內執行此動作。 發生變更時,必須有一個活躍的實例 Transaction 與商店相關聯。 這適用於所有模型元素、關聯性、圖形、圖表及其屬性。

事務機制可協助您避免不一致的狀態。 如果在交易期間發生錯誤,則會回復所有變更。 如果使用者執行復原命令,則每個最近的交易都會被視為單一步驟。 使用者無法復原最近變更的部分,除非您明確地將它們放入個別交易中。

開啟交易

管理交易最方便的方法是將 try...catch 語句包含在 using 語句中:

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.
}

如果在變更期間發生阻止final Commit() 的例外狀況,則Store將重設為其先前的狀態。 這可協助您確保錯誤不會讓模型處於不一致的狀態。

您可以在一筆交易中進行任意數量的更改。 您可以在活動中的交易內開啟新交易。 巢狀交易必須在外層交易結束之前認可或復原。 如需詳細資訊,請參閱屬性的 TransactionDepth 範例。

在處置交易之前,若要使您的變更永久化,您應該確認Commit該交易。 如果發生未在交易內攔截的例外狀況,Store 將會重設為變更前的狀態。

復原交易

若要確保市集在交易之前保持或還原到其狀態,您可以使用下列任一策略:

  1. 引發在交易範圍內未被攔截的例外狀況。

  2. 顯式地回復交易:

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

交易不會影響非存放區物件

交易僅控制商店的狀態。 它們無法恢復對外部項目所做的部分變更,例如您在 DSL 定義之外使用普通類型宣告的檔案、資料庫或物件。

如果例外狀況可能會讓這類變更與市集不一致,您應該在例外狀況處理常式中處理該可能性。 確保外部資源與存放區物件保持同步的其中一種方式,是使用事件處理常式,將每個外部物件耦合至存放區內元素。 如需詳細資訊,請參閱 事件處理常式在模型外部傳播變更

規則會在交易完成後觸發

在交易結束且在交易處理之前,系統會觸發附加到儲存中元素的規則。 每條規則都是一種方法,應用於已更改的模型元素。 例如,有一些「修正」規則會在模型元素變更時更新形狀的狀態,並在建立模型元素時創建形狀。 沒有具體的開火順序。 規則所做的變更可能會引發另一個規則。

您可以定義自己的規則。 如需規則的詳細資訊,請參閱 回應與傳播變更

規則不會在復原、重做或回退命令後觸發。

交易內容

每筆交易都有一個字典,您可以在其中存儲您想要的任何信息:

store.TransactionManager

.CurrentTransaction.TopLevelTransaction

.Context.Add(aKey, aValue);

這對於在規則之間傳輸資訊特別有用。

交易狀態

在某些情況下,如果變更是由復原或重做交易所造成,則需要避免傳播變更。 例如,如果您撰寫屬性值處理常式,以更新存放區中的另一個值,則可能會發生這種情況。 因為復原作業會將存放區中的所有值重設為先前的狀態,所以不需要計算更新的值。 使用這段程式碼:

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

當存放區最初從檔案載入時,規則可能會觸發。 若要避免回應這些變更,請使用:

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