.NET Framework 2.0 - Transações com o Namespace System.Transactions

Leonardo Bruno Lima

Aplica-se a: Visual Studio 2005 (Whidbey), Framework 2.0 Beta 2

Linguagem de programação: Visual Basic .NET

Resumo: Veremos nessa matéria, o que há de novo em relação a transações no . NET Framework 2.0 e o que isso tem de vantagem em relação ao modelo atual.

No ADO.NET 1.0 e 1.1, temos o objeto SqlTransaction que implementa a interface IDbTransaction, e que é usando explicitamente para gerenciar uma transação. Ele é instanciado através do método BeginTransaction do objeto Connention. Se tudo der certo, chamamos o método Commit, caso contrário o método RollBack. Tudo isso explicitamente.

O que esse método tem de ruim?

Se você esta utilizando um único banco de dados e um único objeto, você não terá problemas. Mas, coloque nesse cenário, mais objetos interagindo uns com os outros e todos precisando participar de uma mesma transação. Começou a complicar o meio de campo, mas o jogo ainda não está perdido. Apenas precisamos definir que objeto será o responsável por abrir a conexão, que objeto será responsável por realizar o Commit e RollBack, como esse objeto saberá o estado dos outros objetos, como esse objeto informará aos outros objetos o estado da transação, etc.

Você pode perceber que o trabalho será bem maior, embora seja perfeitamente possível realizar.

Agora imagine esse mesmo cenário, utilizando duas ou mais base de dados. Neste caso, temos uma transação distribuída. Nesse ponto, tornasse impraticável o controle da situação sem usar recursos externos como um gerenciador de transações, que no caso do Windows é o DTC (Distributed Transaction Cordenator). O DTC usa um protocolo chamado OLE Transactions (OleTx), que gerencia transações entre de componentes, processos e máquinas. Para usarmos o DTC em .NET, utilizanmos o Namespace EnterpriseService. Utilizar o EntrepriseService, é a saída mais viável para enfrentar a situação apresentada.

Veja um exemplo do uso do EnterpriseService:

Imports System.EnterpriseService

<Transaction>
Public Class Teste 
Inherits ServicedComponent

<Autocomplete>
Public Function GerarDuplicatas as Boolean
    'Realizar operações no banco de dados, bem como chama outros objetos que também realizem tais operações.
End Function

End Class

É uma boa solução? Bem, se não for boa, pelo menos é a "menos ruim". As vantagens são obvias. Veja algumas desvantagens:

- Força a herança de ServicedComponent, o que em muitos casos não é interessante
- Degradação de performance
- Os objeto são Just-in-time activated, ou seja, "dificulta" o uso de objetos que querem manter estado
- Os objetos são sempre Thread-safe, ou seja, múltiplas threads não podem participar de uma mesma transação.

Enfim, estamos limitados a escolher entre o modelo não distribuído com o objeto Transaction e o modelo distribuído com o Namespace EnterpriseService.

E o que vem por aí?

No Framework 2.0 temos dois novos tipos gerenciadores de transação e o Namespace Transactions.

Os dois tipos de gerenciadores transação são: LTM - Lightweight Transaction Manager e o OleTX Transaction Manager, que podem ser utilizados de forma implícita (automática) ou explícita (manual).

O LTM é usado para gerenciar transações dentro de um único processo e que envolva o uso de um único recurso durável, com uma base de dados única. Já o OleTX gerencia transações entre processos e até entre máquinas distintas, além de gerenciar mais de um recurso durável.

O mais interessante é que o desenvolvedor não precisa interagir com esses gerenciados diretamente, isso é feito pela infra-estrutura .NET, que detecta a necessidade do uso de um ou outro, e faz a "promoção" caso necessário (Transaction Manager Promotion).

Exemplo: Suponha que um objeto interaja com um banco de dados, isso requer apenas o uso do LTM, o que trará mais performance. Mas digamos que esse objeto seja chamado a partir de outro objeto que iniciou uma transação. Se isso for verdade, o nosso objeto sofrerá uma promoção e usará o OleTX, e uma vez que ele foi promovido, assim permanecerá até o termino da transação. Só complementando, todos os objetos sempre iniciam uma transação usando o LTM Transaction Manager.

Um detalhe deve ser lembrado. O Namespace Transaction não faz parte do ADO.NET nem do Namespace System.Data, e é essa separação que permite o gerenciamento de transações que utilizem qualquer tipo de recurso incluindo banco de dados Sql Server 2000 e 2005 (Yukon).

Vamos ver um exemplo de transação utilizando LTM:

No clique de um botão coloque o seguinte código:

Try
   Using oTrans As New TransactionScope
      Using oConn As New SqlConnection("...")
         Dim oComm As New SqlCommand("...", oConn)
         '
         oConn.Open()
         oComm.ExecuteNonQuery()
         oConn.Close()
      End Using
      '
      oTrans.Complete()
   End Using
Catch ex As Exception 
   Messagebox.Show ex.Message	
End Try

No código acima, podemos notar mais uma novidade do Visual Basic .NET 2005, o bloco "Using", o qual garante que o recurso alocado será descartado quando não mais necessário, caso o mesmo implemente a interface IDisposable. Temos também a criação do objeto TransactionScope, garantirá a execução do código em um escopo transacional. Quando a conexão é aberta, ela é automáticamente enfileirada na transação corrente e irá participar dela até o fim. O método Complete do objeto TransactionScope finaliza a transação, portanto, só chame-o ao finalizar todas as operações.

Como vocês puderam reparar, eu não instanciei nenhum objeto de transação explicitamente, portanto o que eu fiz uso de transação implícita. Podemos também utilizar a transação explícita, instanciando os objetos do Namespace Transactions, mas na maioria dos casos não será necessário.

Conclusão: O Namespace System.Transactions é bem fácil e rápido de usar, além de não ter a necessidade de forçar a sua classe a herdar de ServicedComponent, o que abre novas possibilidades no design de aplicações distribuídas. O recurso de promoção de transação LTM para transação distribuída sem a necessidade de uma linha de código sequer, nos dá uma produtividade jamais vista.

Até a próxima.

Leonardo Bruno Lima
lblima_net@hotmail.com
Microsoft MVP (Most Valuable Professional)
Trabalha com desenvolvimento de aplicações .NET desde 2001. Ministra cursos sobre a plataforma .NET, é consultor de tecnologia e desenvolvedor de sistemas na RR Consultoria e Sistemas (Fortaleza - CE).
Atualmente está dedicado ao desenvolvimento de um sistema ERP utilizando a plataforma .NET