Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A CommittableTransaction classe fornece uma maneira explícita para 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 autor da aplicação precisa chamar de forma específica os métodos Commit e Rollback para efetuar ou abortar a transação.
Visão geral da classe CommittableTransaction
A CommittableTransaction classe deriva da Transaction classe, portanto, fornecendo toda a funcionalidade desta última. Especificamente útil é o método Rollback na classe Transaction, que pode também ser usado para reverter um objeto CommittableTransaction.
A Transaction classe é semelhante à classe, CommittableTransaction 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 participar e votar na transação, mas apenas o criador do objeto CommittableTransaction tem a capacidade de confirmar a transação.
Você deve observar o seguinte ao trabalhar com a CommittableTransaction classe,
Criar uma CommittableTransaction transação não define a transação ambiente. Você precisa definir e redefinir especificamente a transação de ambiente para garantir que os gestores de recursos atuem sob o contexto de transação correto, quando apropriado. A maneira de definir a transação de ambiente atual é definindo a propriedade static Current no objeto global Transaction .
Um CommittableTransaction objeto não pode ser reutilizado. Depois que um CommittableTransaction objeto for confirmado ou revertido, ele não poderá ser usado novamente em uma transação. Ou seja, não pode ser definido como o contexto de transação ambiente atual.
Criando uma 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 da transação ambiental. Portanto, qualquer operação em um gerenciador de recursos não faz parte dessa transação. A propriedade static Current no objeto global Transaction é usada para definir ou recuperar a transação de ambiente e o aplicativo deve defini-la manualmente para garantir que os gerentes de recursos possam participar da transação. Também é uma boa prática salvar a transação de ambiente antiga e restaurá-la quando 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 notar que, até que um CommittableTransaction tenha sido confirmado ou revertido, 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 do aplicativo 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 tempo substancial, pois pode envolver acesso a vários bancos de dados e possível latência de rede. Quando quiser evitar bloqueios 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 BeginCommit e EndCommit métodos da CommittableTransaction classe permitem que você faça isso.
Você pode chamar BeginCommit para despachar o atraso de commit para uma thread do grupo de threads. Você também pode ligar EndCommit para determinar se a transação foi realmente confirmada. Se a transação não foi confirmada por qualquer motivo, EndCommit gera uma exceção de transação. Se a transação ainda não estiver confirmada no momento EndCommit em que for chamada, o chamador será bloqueado até que a transação seja confirmada ou abortada.
A maneira mais fácil de fazer uma confirmação assíncrona é fornecendo um método de retorno de chamada, que será chamado quando a confirmação for finalizada. No entanto, você deve chamar o EndCommit método no objeto original CommittableTransaction usado para invocar a chamada. Para obter esse objeto, podes fazer downcast do parâmetro IAsyncResult do método de retorno de chamada, uma vez que a classe CommittableTransaction implementa 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
}
}