Transações Locais
As transações no ADO.NET são usadas quando você deseja vincular várias tarefas para que elas sejam executadas como uma única unidade de trabalho. Por exemplo, imagine que um aplicativo executa duas tarefas. Primeiro, ele atualiza uma tabela com informações do pedido. Em segundo lugar, atualiza uma tabela que contém informações de inventário, debitando os itens encomendados. Se uma das tarefas falhar, ambas as atualizações serão revertidas.
Determinando o tipo de transação
Uma transação é considerada uma transação local quando é uma transação monofásica e é tratada diretamente pelo banco de dados. Uma transação é considerada uma transação distribuída quando é coordenada por um monitor de transações e usa mecanismos à prova de falhas (como confirmação em duas fases) para a resolução da transação.
Cada um dos provedores de dados do .NET Framework tem seu próprio Transaction
objeto para executar transações locais. Se você precisar que uma transação seja executada em um banco de dados do SQL Server, selecione uma System.Data.SqlClient transação. Para uma transação Oracle, use o System.Data.OracleClient provedor. Além disso, há uma DbTransaction classe que está disponível para escrever código independente do provedor que requer transações.
Nota
As transações são mais eficientes quando são realizadas no servidor. Se você estiver trabalhando com um banco de dados do SQL Server que faz uso extensivo de transações explícitas, considere escrevê-las como procedimentos armazenados usando a instrução Transact-SQL BEGIN TRANSACTION.
Executando uma transação usando uma única conexão
No ADO.NET, você controla as transações com o Connection
objeto. Você pode iniciar uma transação local com o BeginTransaction
método. Depois de iniciar uma transação, você pode inscrever um comando nessa transação com a Transaction
propriedade de um Command
objeto. Em seguida, você pode confirmar ou reverter modificações feitas na fonte de dados com base no sucesso ou falha dos componentes da transação.
Nota
O EnlistDistributedTransaction
método não deve ser usado para uma transação local.
O escopo da transação é limitado à conexão. O exemplo a seguir executa uma transação explícita que consiste em dois comandos separados no try
bloco . Os comandos executam instruções INSERT na tabela Production.ScrapReason no banco de dados de exemplo do SQL Server AdventureWorks, que são confirmadas se nenhuma exceção for lançada. O código no bloco reverte catch
a transação se uma exceção for lançada. Se a transação for abortada ou a conexão for fechada antes da conclusão da transação, ela será revertida automaticamente.
Exemplo
Siga estas etapas para executar uma transação.
Chame o BeginTransaction SqlConnection método do objeto para marcar o início da transação. O BeginTransaction método retorna uma referência à transação. Essa referência é atribuída aos SqlCommand objetos listados na transação.
Atribua o
Transaction
objeto à Transaction propriedade do SqlCommand a ser executado. Se um comando for executado em uma conexão com uma transação ativa e oTransaction
objeto não tiver sido atribuído àTransaction
propriedade doCommand
objeto, uma exceção será lançada.Execute os comandos necessários.
Chame o Commit SqlTransaction método do objeto para concluir a transação ou chame o Rollback método para finalizar a transação. Se a conexão for fechada ou descartada antes que os Commit métodos ou Rollback tenham sido executados, a transação será revertida.
O exemplo de código a seguir demonstra a lógica transacional usando ADO.NET com o Microsoft SQL Server.
using (SqlConnection connection = new(connectionString))
{
connection.Open();
// Start a local transaction.
SqlTransaction sqlTran = connection.BeginTransaction();
// Enlist a command in the current transaction.
SqlCommand command = connection.CreateCommand();
command.Transaction = sqlTran;
try
{
// Execute two separate commands.
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
command.ExecuteNonQuery();
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
command.ExecuteNonQuery();
// Commit the transaction.
sqlTran.Commit();
Console.WriteLine("Both records were written to database.");
}
catch (Exception ex)
{
// Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message);
try
{
// Attempt to roll back the transaction.
sqlTran.Rollback();
}
catch (Exception exRollback)
{
// Throws an InvalidOperationException if the connection
// is closed or the transaction has already been rolled
// back on the server.
Console.WriteLine(exRollback.Message);
}
}
}
Using connection As New SqlConnection(connectionString)
connection.Open()
' Start a local transaction.
Dim sqlTran As SqlTransaction = connection.BeginTransaction()
' Enlist a command in the current transaction.
Dim command As SqlCommand = connection.CreateCommand()
command.Transaction = sqlTran
Try
' Execute two separate commands.
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
command.ExecuteNonQuery()
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
command.ExecuteNonQuery()
' Commit the transaction
sqlTran.Commit()
Console.WriteLine("Both records were written to database.")
Catch ex As Exception
' Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message)
Try
' Attempt to roll back the transaction.
sqlTran.Rollback()
Catch exRollback As Exception
' Throws an InvalidOperationException if the connection
' is closed or the transaction has already been rolled
' back on the server.
Console.WriteLine(exRollback.Message)
End Try
End Try
End Using