Transações Distribuídas no WCF

Olá a todos,

Nesse post vamos demonstrar como podemos ter transações distribuídas utilizando serviços WCF sendo propagadas para chamadas de diversos métodos que podem pertencer a diferentes serviços. Esse cenário pode ser desenvolvido utilizando dois modelos: um proprietário do WCF para situações onde existirão somente serviços construídos nessas tecnologia e outro utilizando o protocolo WS-AT (WS Atomic Transaction), que é um protocolo de controle de transações compatível com diversas tecnologias para desenvolvimento de webservices.

A estrutura de transação do WCF (para os dois tipo de protocolos citados acima) utiliza o modelo presente a partir do .Net Framework 2.0, onde temos dois tipos de objetos: Transacion e TransactionScope. Nesse modelo de programação o desenvolvedor normalmente lida com o objeto TransactionScope pois a duração da transação e as operações transacionadas são determinadas pela vida desse tipo de objeto. Temos nesse tipo de objeto três propriedades básicas que podem ser configuradas: seu período de timeout (TransactionTimeout), seu nível de isolamento (TransactionIsolationLevel) e se ela será confirmada automaticamente ou não (TransactionAutoCompleteOnSessionClose).

Para um método de um serviço WCF pertencer a uma transação ele deve ser decorado com o atributo TransactionFlow, onde deve ser informado a obrigatoriedade ou não da transação. Essa configuração é informada a partir de um parâmetro, que pode assumir três valores diferentes, passado para o atributo. O valor Allowed indica que um método pode ou não pertencer a uma transação, desse modo quando a chamada desse método pertencer a uma transação as operações realizadas por ele também estarão no contexto da transação. Porém se a chamada não pertencer a uma transação o método será executado com suas operações não transacionadas. O valor NotAllowed informa que o método não será executado em contexto de transação, ou seja, mesmo que a chamada possua uma transação ativa as operações realizadas pelo método com esse valor não estarão no contexto dessa transação nem de qualquer outra. Por último o valor Mandatory obriga o método a possuir uma transação. Nessa configuração caso a chamada não possua uma transação ativa será iniciada uma nova transação com o escopo desse método.

Passaremos agora para o desenvolvimento do nosso exemplo. Nele teremos dois serviços WCF onde cada um possuirá um método que pode ser chamado no contexto de uma transação. Um dos métodos faz a inserção em um banco de dados enquanto o outro enviará uma mensagem para uma fila MSMQ. Demonstraremos então o funcionamento da transação distribuída utilizando mais de um recurso. Começaremos então criando uma fila transacional no MSMQ e uma tabela em um banco de dados no SQL Server.

Codigo para gerar a tabela utilizada no exemplo

O próximo passo é construir a estrutura para o código que será composta de um Windows Service para hospedar os serviços WCF e de uma aplicação do tipo Console que será o iniciador das chamadas, controlando a transação. Adicionados esses projetos na solução adicione dois serviços WCF no projeto do Windows Service e faça as alterações necessárias nesse projeto para subir os serviços. Nesse exemplo as configurações serão controladas a partir do arquivo app.config dos projetos.

Estrutura da solucao

Adicionados os dois serviços WCF no projeto do Windows Service vamos iniciar as configurações para que eles suportem chamadas em contexto de transação. O primeiro item a ser alterado é o contrato de cada serviço. Nele será adicionado o atributo TransactionFlow na definição do método, especificando o seu suporte a transações. Essa alteração deve ser realizada para os contratos dos dois serviços.

Codigo do contrato do primeiro servico

Após a alteração dos dois contratos devemos modificar também o código da sua implementação, adicionando o atributo TransactionScopeRequired para o método.

Codigo inicial do metodo do segundo servico

Basta agora alterarmos o arquivo app.config do Windows Service para termos nossos serviços WCF suportando transações. Nessa configuração será alterada a configuração do binding, passando o valor do atributo transactionFlow como true e informando essa configuração nos endpoints:

Modificacoes no arquivo de configuracao

Vamos então terminar o código dos serviços, onde o primeiro fará a inserção no banco de dados e o segundo enviará uma mensagem para o MSMQ, ambos no contexto de uma transação:

Codigo para enviar a mensagem em contexto de transacao

Codigo para inserir o registro na tabela

Passaremos agora a desenvolver a chamada da aplicação que inicia essa transação. Nesse exemplo utilizamos um projeto do tipo Console Application, porém outros tipos de projetos podem ser utilizados. O primeiro passo é gerar os proxies dos serviços, para isso podemos iniciar a versão de Debug do Windows Service a partir de uma linha de comando, solicitando ao Visual Studio a geração dos proxies dos dois serviços. Após gerados os proxies basta criar um objeto do tipo TransactionScope e realizar as chamadas dos serviços durante o seu ciclo de vida, como demonstrado abaixo:

Codigo da aplicacao que controla a transacao

Temos então nosso exemplo pronto. Podemos iniciar o Windows Service para abrir os serviços. Em seguida execute a aplicação que inicia a transação e realiza as chamadas. Poderemos ver que ao final da execução será adicionado um registro na tabela e será enviada a mensagem para a fila. Vamos agora retirar o comentário da linha de código na aplicação console para forçar o disparo de uma exceção com o intuito de forçar o rollback da transação. Ao executar todo o ciclo novamente veremos que a exceção foi disparada e não foi incluído o registro na tabela nem enviada a mensagem para a fila. Como sempre adicionei o exemplo no meu Sky Drive com o nome WCF_Transacional.

Abraços a todos e até o próximo post.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s