Compartilhar via


Usar transações para atualizar o modelo

As transações garantem que as alterações feitas no repositório sejam tratadas como um grupo. As alterações agrupadas podem ser confirmadas ou revertidas como uma única unidade.

Sempre que o código do programa modifica, adiciona ou exclui qualquer elemento na Loja no SDK de Visualização e Modelagem do Visual Studio, ele deve fazer isso dentro de uma transação. Deve haver uma instância ativa de Transaction associada à Loja quando a alteração ocorrer. Isso se aplica a todos os elementos de modelo, relações, formas, diagramas e suas propriedades.

O mecanismo de transação ajuda você a evitar estados inconsistentes. Se ocorrer um erro durante uma transação, todas as alterações serão revertidas. Se o usuário executar um comando Desfazer, cada transação recente será tratada como uma única etapa. O usuário não pode desfazer partes de uma alteração recente, a menos que você as coloque explicitamente em transações separadas.

Abrindo uma transação

O método mais conveniente de gerenciar uma transação é com uma using declaração colocada em uma try...catch declaração:

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

Se ocorrer uma exceção que impeça a final Commit() durante as alterações, o Repositório será redefinido para o estado anterior. Isso ajuda você a garantir que os erros não deixem o modelo em um estado inconsistente.

Você pode fazer qualquer número de alterações dentro de uma transação. Você pode abrir novas transações dentro de uma transação ativa. As transações aninhadas devem ser confirmadas ou revertidas antes do término da transação que contém. Para obter mais informações, consulte o exemplo da TransactionDepth propriedade.

Para tornar suas alterações permanentes, você deve Commit a transação antes que ela seja descartada. Se ocorrer uma exceção que não seja capturada dentro da transação, a Loja será redefinida para seu estado antes das alterações.

Revertendo uma transação

Para garantir que a Loja permaneça ou reverta para seu estado antes da transação, você pode usar uma destas táticas:

  1. Gerar uma exceção que não é capturada dentro do escopo da transação.

  2. Reverta explicitamente a transação:

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

Transações não afetam objetos não armazenados

As transações regem apenas o estado da Loja. Eles não podem desfazer alterações parciais feitas em itens externos, como arquivos, bancos de dados ou objetos que você declarou com tipos comuns fora da definição de DSL.

Se uma exceção puder deixar essa alteração inconsistente com a Loja, você deverá lidar com essa possibilidade no manipulador de exceção. Uma maneira de garantir que os recursos externos permaneçam sincronizados com os objetos da Loja é associar cada objeto externo a um elemento na loja usando manipuladores de eventos. Para obter mais informações, consulte Manipuladores de Eventos Propagam Alterações Fora do Modelo.

Regras são ativadas no final de uma transação

No final de uma transação, antes que a transação seja descartada, as regras anexadas aos elementos na loja são acionadas. Cada regra é um método que é aplicado a um elemento de modelo que foi alterado. Por exemplo, há regras de "correção" que atualizam o estado de uma Forma quando seu elemento de modelo é alterado e que criam uma Forma quando um elemento de modelo é criado. Não há nenhuma ordem de disparo especificada. Uma alteração feita por uma regra pode ativar outra regra.

Você pode definir suas próprias regras. Para obter mais informações sobre regras, consulte Responder e propagar alterações.

As regras não são disparadas após um comando de desfazer, um comando de refazer ou um comando de reversão.

Contexto da transação

Cada transação tem um dicionário no qual você pode armazenar qualquer informação desejada:

store.TransactionManager

.CurrentTransaction.TopLevelTransaction

.Context.Add(aKey, aValue);

Isso é especialmente útil para transferir informações entre regras.

Estado da transação

Em alguns casos, você precisa evitar propagar uma alteração se a alteração for causada por desfazer ou refazer uma transação. Isso pode acontecer, por exemplo, se você escrever um manipulador de valor de propriedade que possa atualizar outro valor na Store. Como a operação de desfazer restaura todos os valores no Armazenamento para seus estados anteriores, não é necessário calcular valores atualizados. Use este código:

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

As regras podem ser acionadas quando o repositório está sendo carregado inicialmente de um arquivo. Para evitar responder a essas alterações, use:

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