Utiliser des transactions pour mettre à jour le modèle

Les transactions permettent de s’assurer que les modifications apportées au magasin sont traitées comme un groupe. Les modifications regroupées peuvent être validées ou restaurées comme une seule unité.

À chaque fois que votre code de programme modifie, ajoute ou supprime un élément dans le Store dans le Kit SDK Visualisation et modélisation Visual Studio, il doit le faire à l’intérieur d’une transaction. Une instance active de Transaction doit être associée au Store lorsque la modification se produit. Cela s’applique à l’ensemble des éléments de modèle, des relations, des formes, diagrammes et de leurs propriétés.

Le mécanisme de transaction vous aide à éviter les états incohérents. Si une erreur se produit pendant une transaction, toutes les modifications sont restaurées. Si l’utilisateur exécute une commande Annuler, chaque transaction récente est traitée comme une seule étape. L’utilisateur ne peut pas annuler certaines parties d’une modification récente, sauf si vous les placez explicitement dans des transactions distinctes.

Ouverture d’une transaction

La méthode la plus pratique pour gérer une transaction est d’utiliser une instruction using intercalée dans une instruction 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.
}

Si une exception qui empêche l’opération Commit() finale se produit pendant les modifications, le Store est réinitialisé à son état précédent. Cela vous permet de vous assurer que les erreurs ne laissent pas le modèle dans un état incohérent.

Vous pouvez apporter autant de modifications que nécessaire à l’intérieur d’une transaction. Vous pouvez ouvrir de nouvelles transactions à l’intérieur d’une transaction active. Les transactions imbriquées doivent se valider ou se restaurer avant la fin de la transaction contenante. Pour plus d’informations, consultez l’exemple pour la propriété TransactionDepth.

Pour rendre vos modifications permanentes, vous devez faire un Commit de la transaction avant qu’elle soit éliminée. S’il se produit une exception qui n’est pas interceptée à l’intérieur de la transaction, le Store reprend l’état qui était le sien avant les modifications.

Restauration d’une transaction

Pour vous assurer que le Store reste dans le même état ou qu’il revient à son état avant la transaction, vous pouvez utiliser l’une des tactiques suivantes :

  1. Déclenchez une exception qui n’est pas interceptée dans l’étendue de la transaction.

  2. Restauration explicite de la transaction :

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

Les transactions n’affectent pas les objets autres que le magasin

Les transactions régissent uniquement l’état du Store. Elles ne peuvent pas annuler les modifications partielles qui ont été apportées à des éléments externes tels que des fichiers, des bases de données ou des objets que vous avez déclarés avec des types ordinaires en dehors de la définition DSL.

Si une exception est susceptible de laisser une telle modification incohérente dans le Store, vous devez traiter cette possibilité dans le gestionnaire d’exceptions. Une façon de s’assurer que les ressources externes restent synchronisées avec les objets Store consiste à associer chaque objet externe à un élément dans le magasin à l’aide de gestionnaires d’événements. Pour plus d’informations, consultez Propagation de modifications en dehors du modèle par des gestionnaire d’événements.

Déclenchement de règles à la fin d’une transaction

À la fin d’une transaction, avant sa suppression, les règles attachées aux éléments du magasin sont déclenchées. Chaque règle est une méthode qui est appliquée à un élément de modèle qui a changé. Par exemple, il existe des règles de « correction » qui mettent à jour l’état d’une Forme lorsque son élément de modèle a changé et qui créent une Forme lors de la création d’un élément de modèle. Il n’y a pas d’ordre de déclenchement spécifié. Une modification apportée par une règle peut déclencher une autre règle.

Vous pouvez définir vos propres règles. Pour plus d’informations sur les règles, consultez Répondre aux modifications et les propager.

Les règles ne se déclenchent pas après une commande d’annulation, de rétablissement ou de restauration.

Contexte de transaction

Chaque transaction a un dictionnaire dans lequel vous pouvez stocker toutes les informations souhaitées :

store.TransactionManager

.CurrentTransaction.TopLevelTransaction

.Context.Add(aKey, aValue);

Cela est particulièrement utile pour transférer des informations entre des règles.

État des transactions

Dans certains cas, vous devez éviter de propager une modification si elle est provoquée par l’annulation ou la restauration d’une transaction. Cela peut se produire, par exemple, si vous écrivez un gestionnaire de valeur de propriété qui peut mettre à jour une autre valeur dans le Store. Étant donné que l’opération d’annulation réinitialise toutes les valeurs du Store sur leurs états précédents, il n’est pas nécessaire de calculer les valeurs mises à jour. Utilisez ce code :

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

Les règles peuvent être déclenchées lorsque le magasin est en cours de chargement initial à partir d’un fichier. Pour éviter de répondre à ces modifications, utilisez :

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