Usar System.Transactions
Aplica-se:SQL Server
O namespace System.Transactions
fornece uma estrutura de transação totalmente integrada com ADO.NET e integração clr (common language runtime) do SQL Server. A classe System.Transactions.TransactionScope
torna um bloco de código transacional ao inscrever implicitamente conexões em uma transação distribuída. Você deve chamar o método Complete
no final do bloco de código marcado pelo TransactionScope
. O método Dispose
é invocado quando a execução do programa sai de um bloco de código, fazendo com que a transação seja descontinuada se o método Complete
não for chamado. Se uma exceção foi lançada que faz com que o código deixe o escopo, a transação será considerada descontinuada.
Recomendamos que você empregue um bloco using
para garantir que o método Dispose
seja chamado no objeto TransactionScope
quando o bloco using
for encerrado. A falha na confirmação ou reversão de transações pendentes pode prejudicar seriamente o desempenho porque o tempo limite padrão para o TransactionScope
é de um minuto. Se você não usar uma instrução using
, deverá executar todo o trabalho em um bloco Try
e chamar explicitamente o método Dispose
no bloco Finally
.
Se ocorrer uma exceção no TransactionScope
, a transação será marcada como inconsistente e será abandonada. Ele reverte quando o TransactionScope
é descartado. Se nenhuma exceção ocorrer, as transações participantes serão confirmadas.
TransactionScope
deve ser usado somente quando fontes de dados locais e remotas ou gerenciadors de recursos externos estiverem sendo acessados, pois TransactionScope
sempre faz com que as transações promovam, mesmo que ela esteja sendo usada apenas em uma conexão de contexto.
A classe TransactionScope
cria uma transação com um System.Transactions.Transaction.IsolationLevel
de Serializable
por padrão. Dependendo do seu aplicativo, talvez você queira considerar abaixar o nível de isolamento para evitar uma contenção elevada em seu aplicativo.
Observação
É recomendável executar apenas atualizações, inserções e exclusões em transações distribuídas em servidores remotos, pois isso consume recursos de banco de dados significativos. Se a operação for executada no servidor local, uma transação distribuída não será necessária e uma transação local será suficiente.
SELECT
instruções podem bloquear recursos de banco de dados desnecessariamente e, em alguns cenários, pode ser necessário usar transações para seleções. Qualquer trabalho que não seja do banco de dados deve ser executado fora do escopo da transação, a menos que envolva outros gerenciadores de recursos transacionados.
Embora uma exceção no escopo da transação impeça a confirmação da transação, a classe TransactionScope
não tem nenhuma provisão para reverter as alterações feitas pelo código fora do escopo da própria transação. Se você precisar executar alguma ação quando a transação for revertida, você deverá escrever sua própria implementação da interface System.Transactions.IEnlistmentNotification
e se inscrever explicitamente na transação.
Exemplos
Para trabalhar com System.Transactions
, você deve ter uma referência ao arquivo System.Transactions.dll.
O código a seguir demonstra como criar uma transação que pode ser promovida em duas instâncias diferentes do SQL Server. Essas instâncias são representadas por dois objetos System.Data.SqlClient.SqlConnection
diferentes, que são encapsulados em um bloco de TransactionScope
. O código cria o bloco TransactionScope
com uma instrução using
e abre a primeira conexão, que a inseri automaticamente no TransactionScope
. A transação é inscrita inicialmente como uma transação lightweight, não uma transação distribuída completa. O código pressupõe a existência de lógica condicional (omitida para brevidade). Ele abre a segunda conexão somente se for necessário, inscrevendo-a no TransactionScope
.
Quando a conexão é aberta, a transação é automaticamente elevada a uma transação distribuída completa. Em seguida, o código invoca TransactionScope.Complete
, que confirma a transação. O código descarta as duas conexões ao sair das instruções using
para as conexões. O método TransactionScope.Dispose
para o TransactionScope
é chamado automaticamente no encerramento do bloco de using
do TransactionScope
. Se uma exceção tiver sido lançada em qualquer ponto do bloco TransactionScope
, Complete
não será chamada e a transação distribuída será revertida quando o TransactionScope
for descartado.
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection connection1 = new
SqlConnection(connectString1))
{
// Opening connection1 automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Do work in the first connection.
// Assumes conditional logic in place where the second
// connection will only be opened as needed.
using (SqlConnection connection2 = new
SqlConnection(connectString2))
{
// Open the second connection, which enlists the
// second connection and promotes the transaction to
// a full distributed transaction.
connection2.Open();
// Do work in the second connection.
}
}
// The Complete method commits the transaction.
transScope.Complete();
}