Páginas

segunda-feira, 5 de setembro de 2011

Distribuindo Transação no WCF

Existem cenários em que é necessário realizar transações distribuídas e, ainda mais onde a arquitetura da solução foi desenvolvida utilizando o conceito de serviços. Para isto o WCF (Windows Communication Foundation) permite que você controle a transação contida no método através da chamada no client (isto, somente se no server estiver habilitado).

A implementação é bem simples e requer que o MSDTC das máquinas estejam habilitados e configurados corretamente, isto garantirá que as máquinas tenham uma comunicação eficaz e garanta o conceito ACID na ação.

Exemplo de configuração do MSDTC:

Para acessar o MSDTC, acesse o "Control Panel" do Windows e entre na opção "Administrative Tools" e logo em seguida em "Component Services". Ao abrir a janela, expanda os itens "Component Services" e "Computers". Clique com o botão direito sobre o "My Computer" e acesse o item "Properties", conforme imagem abaixo.



Na aba MSDTC, habilite-o e realize a configuração.

Exemplo de configuração:


Exemplo de configuração do "Security Configuration":


Habilitando a transação distribuída no código:

Em primeiro momento para habilitar a transação no serviço você necessitará alterar o arquivo de configuração, colocando no binding o atributo transactionFlow e também habilitar a sessão (reliableSession), conforme exemplo abaixo que expoe o protocolo net.tcp:

<netTcpBinding>
  <binding name="TransacaoBinding" transactionFlow="true">
    <reliableSession enabled="true"/>
    <security />
  </binding>
</netTcpBinding>

Na interface do serviço precisaremos identificar que aquele contrato tem o atributo SessionMode como Required no attribute ServiceContract.
Para todos os métodos que necessitarem da transação distribuída, deve-se adicionar o attribute TransactionFlow com a opção Allowed (permite transação) ou Mandatory (transação obrigatória).

//Interface do Serviço
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ITesteService
{
   [OperationContract]
   [TransactionFlow(TransactionFlowOption.Allowed)]
   bool EfetuarTransferencia(...);
}

Na implementação do serviço será necessário habilitar o atributo TransactionScopeRequired, informando que ele é necessário para este caso.
Dentro da implementação do serviço, utilize o objeto TransactionScope com o atributo TransactionScopeOption na opção Required, para que a transação criada pelo client possa ser utilizada e permita que o conceito ACID seja aplicado.

//Implementação do Serviço
[ServiceBehavior()]
public class TesteService : ITesteService
{
   [OperationBehavior(TransactionScopeRequired = true)]
   public bool EfetuarTransferencia(...)
   {
      //Utilize o TransactionScopeOption como Required, para que a transação utilizada seja a mesma da chamada do client.
      using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
      {
         //Realizar alguma ação para gravar em banco de dados.
         ts.Complete();
      }
   }
}

IMPORTANTE: Nesta implementação quando for chamado o método "Complete" do TransactionScope no serviço, o que estiver dentro da transação será marcado como ok e somente se o client realizar o Complete da mesma transação, as ações que participarem desta transação serão aplicadas em definitivo.

Lembrando que no "Dispose" do objeto, as informações são descartadas.


No lado do client:

Para o client, será necessário somente adicionar a referência do serviço e realizar a chamada ao método que requer transação utilizando o "TransactionScopeOption" como "RequiresNew" ou "Required".

Exemplo:
static void Main(string[] args)
{
   using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
   {
      //Realizar alguma ação que necessite da transação

      //Chamar o serviço
      ServiceReference1.TesteServiceClient servico = new ServiceReference1.TesteServiceClient();
      servico.EfetuarTransferencia(...);

      //Commit da transação
      ts.Complete();

      servico.Close();
   }
}


Referências:
MSDN - WS Transaction Flow
MSDN - WCF Transaction Propagation

0 comentários:

Postar um comentário