Usar transacciones para actualizar el modelo

Las transacciones se aseguran de que los cambios realizados en el almacén se tratan como un grupo. Los cambios agrupados se pueden confirmar o revertir como una sola unidad.

Cada vez que el código del programa modifica, agrega o elimina cualquier elemento del almacén en el SDK de visualización y modelado de Visual Studio, debe hacerlo dentro de una transacción. Debe haber una instancia activa de Transaction asociada al almacén cuando se produzca el cambio. Esto se aplica a todos los elementos, las relaciones, las formas y los diagramas del modelo, así como a sus propiedades.

El mecanismo de transacción ayuda a evitar estados incoherentes. Si se produce un error durante una transacción, se revierten todos los cambios. Si el usuario ejecuta un comando Deshacer, cada transacción reciente se trata como un solo paso. El usuario no puede deshacer partes de un cambio reciente, a menos que las coloque explícitamente en transacciones independientes.

Apertura de una transacción

El método más recomendable para administrar una transacción es incluir una instrucción using en una instrucción 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 se produce una excepción que impide que se ejecute la confirmación final (Commit()) durante los cambios, el almacén se restablecerá a su estado anterior. Esto le ayuda a asegurarse de que los errores no dejen el modelo en un estado incoherente.

Puede realizar cualquier número de cambios en una transacción. Puede abrir nuevas transacciones dentro de una transacción activa. Las transacciones anidadas deben confirmarse o revertirse antes de que finalice la transacción contenedora. Para obtener más información, vea el ejemplo de la propiedad TransactionDepth.

Para hacer que los cambios sean permanentes, debe ejecutar Commit en la transacción antes de eliminarla. Si se produce una excepción que no se detecta dentro de la transacción, el almacén se restablecerá a su estado antes de los cambios.

Revertir una transacción

Para asegurarse de que el almacén permanece en su estado, o se revierte a su estado, antes de la transacción, puede usar cualquiera de estos métodos:

  1. Genere una excepción que no se detecte dentro del ámbito de la transacción.

  2. Revierta explícitamente la transacción:

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

Las transacciones no afectan a los objetos que no son de almacén

Las transacciones solo rigen el estado del almacén. No pueden deshacer cambios parciales realizados en elementos externos, como archivos, bases de datos u objetos declarados con tipos normales fuera de la definición de DSL.

Si una excepción puede dejar cambios incoherentes con el almacén, debe tratar esa posibilidad en el controlador de excepciones. Una manera de asegurarse de que los recursos externos permanecen sincronizados con los objetos del almacén es acoplar cada objeto externo a un elemento en el almacén mediante controladores de eventos. Para obtener más información, consulte Controladores de eventos para propagar cambios fuera del modelo.

Las reglas se activan al final de una transacción

Al final de una transacción, antes de eliminarla, se activan las reglas adjuntas a los elementos del almacén. Cada regla es un método que se aplica a un elemento de modelo que ha cambiado. Por ejemplo, hay reglas de "corrección" que actualizan el estado de una forma cuando su elemento de modelo ha cambiado y que crean una forma cuando se crea un elemento de modelo. No hay ningún orden de activación específico. Un cambio realizado por una regla puede desencadenar otra regla.

Puede definir sus propias reglas. Para obtener más información, consulte Respuesta a cambios y propagación de cambios.

Las reglas no se activan después de comandos para deshacer, rehacer o de reversión.

Contexto de transacción

Cada transacción tiene un diccionario en el que puede almacenar la información que quiera:

store.TransactionManager

.CurrentTransaction.TopLevelTransaction

.Context.Add(aKey, aValue);

Esto es especialmente útil para transferir información entre reglas.

Estado de las transacciones

En algunos casos, debe evitar propagar un cambio si este se ha producido al deshacer o rehacer una transacción. Esto puede ocurrir, por ejemplo, si escribe un controlador de valores de propiedad que puede actualizar otro valor en el almacén. Dado que la operación de deshacer restablece todos los valores del almacén a sus estados anteriores, no es necesario calcular los valores actualizados. Use este código:

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

Las reglas se pueden activar cuando el almacén se carga inicialmente desde un archivo. Para evitar responder a estos cambios, use:

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