Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A CommittableTransaction classe fornece uma maneira explícita de os aplicativos usarem uma transação, em vez de usar a TransactionScope classe implicitamente. É útil para aplicativos que desejam usar a mesma transação em várias chamadas de função ou várias chamadas de thread. Ao contrário da classe TransactionScope, o gravador de aplicativos precisa chamar especificamente os métodos Commit e Rollback para confirmar ou anular a transação.
Visão geral da classe CommittableTransaction
A CommittableTransaction classe deriva da Transaction classe, fornecendo, portanto, toda a funcionalidade deste último. Especificamente útil é o Rollback método na Transaction classe que também pode ser usado para reverter um CommittableTransaction objeto.
A Transaction classe é semelhante à CommittableTransaction classe, mas não oferece um Commit método. Isso permite que você passe o objeto de transação (ou clones dele) para outros métodos (potencialmente em outros threads) enquanto ainda controla quando a transação é confirmada. O código chamado é capaz de se inscrever e votar na transação, mas somente o criador do CommittableTransaction objeto tem a capacidade de confirmar a transação.
Você deve observar os seguintes itens ao trabalhar com a CommittableTransaction classe,
A criação de uma CommittableTransaction transação não define a transação ambiente. Você precisa definir e redefinir especificamente a transação ambiente, para garantir que os gerenciadores de recursos operem no contexto de transação correto, quando apropriado. A maneira de definir a transação ambiente atual é definindo a propriedade estática Current no objeto global Transaction .
Um CommittableTransaction objeto não pode ser reutilizado. Depois que um CommittableTransaction objeto tiver sido confirmado ou revertido, ele não poderá ser usado novamente em uma transação. Ou seja, ele não pode ser definido como o contexto de transação ambiente atual.
Criando um CommittableTransaction
O exemplo a seguir cria um novo CommittableTransaction e o confirma.
//Create a committable transaction
tx = new CommittableTransaction();
SqlConnection myConnection = new SqlConnection("server=(local)\\SQLExpress;Integrated Security=SSPI;database=northwind");
SqlCommand myCommand = new SqlCommand();
//Open the SQL connection
myConnection.Open();
//Give the transaction to SQL to enlist with
myConnection.EnlistTransaction(tx);
myCommand.Connection = myConnection;
// Restore database to near it's original condition so sample will work correctly.
myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)";
myCommand.ExecuteNonQuery();
// Insert the first record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')";
myCommand.ExecuteNonQuery();
// Insert the second record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')";
myCommand.ExecuteNonQuery();
// Commit or rollback the transaction
while (true)
{
Console.Write("Commit or Rollback? [C|R] ");
ConsoleKeyInfo c = Console.ReadKey();
Console.WriteLine();
if ((c.KeyChar == 'C') || (c.KeyChar == 'c'))
{
tx.Commit();
break;
}
else if ((c.KeyChar == 'R') || (c.KeyChar == 'r'))
{
tx.Rollback();
break;
}
}
myConnection.Close();
tx = null;
tx = New CommittableTransaction
Dim myConnection As New SqlConnection("server=(local)\SQLExpress;Integrated Security=SSPI;database=northwind")
Dim myCommand As New SqlCommand()
'Open the SQL connection
myConnection.Open()
'Give the transaction to SQL to enlist with
myConnection.EnlistTransaction(tx)
myCommand.Connection = myConnection
'Restore database to near it's original condition so sample will work correctly.
myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)"
myCommand.ExecuteNonQuery()
'Insert the first record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')"
myCommand.ExecuteNonQuery()
'Insert the second record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')"
myCommand.ExecuteNonQuery()
'Commit or rollback the transaction
Dim c As ConsoleKeyInfo
While (True)
Console.Write("Commit or Rollback? [C|R] ")
c = Console.ReadKey()
Console.WriteLine()
If (c.KeyChar = "C") Or (c.KeyChar = "c") Then
tx.Commit()
Exit While
ElseIf ((c.KeyChar = "R") Or (c.KeyChar = "r")) Then
tx.Rollback()
Exit While
End If
End While
myConnection.Close()
tx = Nothing
A criação de uma instância de CommittableTransaction não define automaticamente o contexto de transação ambiente. Portanto, qualquer operação em um gerenciador de recursos não faz parte dessa transação. A propriedade estática Current no objeto global Transaction é usada para definir ou recuperar a transação ambiente e o aplicativo deve defini-la manualmente para garantir que os gerenciadores de recursos possam participar da transação. Também é uma boa prática salvar a transação de ambiente antiga e restaurá-la quando você terminar de usar o CommittableTransaction objeto.
Para confirmar a transação, você precisa chamar explicitamente o Commit método. Para reverter uma transação, você deve chamar o Rollback método. É importante observar que até um CommittableTransaction foi confirmada ou revertida, todos os recursos envolvidos nessa transação ainda estão bloqueados.
Um CommittableTransaction objeto pode ser usado em chamadas de função e threads. No entanto, cabe ao desenvolvedor de aplicativos lidar com exceções e chamar especificamente o Rollback(Exception) método em caso de falhas.
Confirmação assíncrona
A CommittableTransaction classe também fornece um mecanismo para confirmar uma transação de forma assíncrona. Uma confirmação de transação pode levar um tempo substancial, pois pode envolver vários acessos de banco de dados e uma possível latência de rede. Quando quiser evitar deadlocks em aplicativos de alta taxa de transferência, você pode usar a confirmação assíncrona para concluir o trabalho transacional o mais rápido possível e executar a operação de confirmação como uma tarefa em segundo plano. Os métodos BeginCommit e EndCommit da classe CommittableTransaction permitem que você faça isso.
Você pode chamar BeginCommit para expedir a demora de confirmação a um thread do pool de threads. Você também pode ligar EndCommit para determinar se a transação foi realmente confirmada. Se a transação não for confirmada por qualquer motivo, EndCommit gerará uma exceção de transação. Se a transação é ainda não foram confirmada no momento EndCommit é chamado, o chamador é bloqueado até que a transação é confirmada ou anulada.
É a maneira mais fácil de fazer uma confirmação assíncrona, fornecendo um método de retorno de chamada a ser chamada quando a confirmação for concluída. No entanto, você deve chamar o EndCommit método no objeto original CommittableTransaction usado para invocar a chamada. Para obter esse objeto, você pode baixar o parâmetro IAsyncResult do método de retorno de chamada, já que a classe CommittableTransaction implementa a classe IAsyncResult.
O exemplo a seguir mostra como uma confirmação assíncrona pode ser feita.
public void DoTransactionalWork()
{
Transaction oldAmbient = Transaction.Current;
CommittableTransaction committableTransaction = new CommittableTransaction();
Transaction.Current = committableTransaction;
try
{
/* Perform transactional work here */
// No errors - commit transaction asynchronously
committableTransaction.BeginCommit(OnCommitted,null);
}
finally
{
//Restore the ambient transaction
Transaction.Current = oldAmbient;
}
}
void OnCommitted(IAsyncResult asyncResult)
{
CommittableTransaction committableTransaction;
committableTransaction = asyncResult as CommittableTransaction;
Debug.Assert(committableTransaction != null);
try
{
using(committableTransaction)
{
committableTransaction.EndCommit(asyncResult);
}
}
catch(TransactionException e)
{
//Handle the failure to commit
}
}