Pergunta

no nosso atual projeto estamos usando ADO.NET Entity Framework como camada de dados para a aplicação.Existem algumas tarefas que exigem a execução de uma transação, porque há um monte de trabalho para fazer no banco de dados.Eu estou usando um TransactionScope para cercar essas tarefas.

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    // Do something...
    transactionScope.Complete();
}

O problema é assim que eu estou usando um TransactionScope uma exceção ocorre:

Do sistema.Dados.EntityException:O provedor subjacente falha em Abrir.---> Sistema.Transações.TransactionManagerCommunicationException:A comunicação com o gerenciador de transação subjacente falhou.---> Sistema.O tempo de execução.InteropServices.COMException (0 x 80004005):Erro HRESULT E_FAIL foi retornado de uma chamada para um componente COM.

Parece que este erro tem que fazer algo com o MSDTC (Microsoft Distributed Transaction Coordinator).Quando eu mudar a configuração de segurança do MSDTC outra exceção é lançada:

Do sistema.Dados.EntityException:O provedor subjacente falha em Abrir.---> Sistema.Transações.TransactionManagerCommunicationException:O acesso de rede para Distributed Transaction Manager (MSDTC) foi desativado.Por favor, habilite DTC para acesso de rede a configuração de segurança para o MSDTC usando a ferramenta Administrativa Serviços de Componentes.

No entanto MSDTC está configurado, o TransactionScope vai causar um erro.Alguém sabe o que está acontecendo de errado aqui?

Foi útil?

Solução 8

Hmm, parece funcionar quando eu mudei o Transactionscopeoption suprimir":

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
{
    ...
}

Todo mundo sabe por quê?

Outras dicas

Por padrão, o MSDTC tem acesso à rede desativado. Para trabalhar, você deve ir para

Painel de controle-> Ferramentas administrativas-> Serviços de componentes-> Serivces de componentes

e verifique as seguintes caixas de seleção Acesso ao DTC da rede, permita a entrada, permita a saída. A autenticação deve ser escolhida de acordo com o seu ambiente. Você também pode querer dar uma olhada em Dtcping Ferramenta para depurar transações distribuídas. Para lhe dar um atalho - pode ser necessário modificar seu registro:

Hklm software políticas microsoft windows nt rpcrestricTremoteClients = 0 hklm software políticas microsoft windows nt rpcenableauthepresolution = 1

Para colocar tudo em funcionamento.

Sim, ele funciona usando o Supress, porque você está dizendo para suprimir ou ignorar a transação ambiente e criar uma nova transação local. Como a transação é local, não é uma transação distribuída, portanto, não está usando o MSDTC, mas você provavelmente não deve usar o supressão e o uso necessário.

Isso significa que está suprimindo qualquer transação que possa estar em vigor atualmente quando você insere seu bloco de código, portanto, qualquer atualização que seu código faça não será revertido se a transação "ambiente" externa decidir reversão.

Este é o artigo que usamos para resolver o nosso próprio problema semelhante:

Problemas de solução de problemas com o msdtc

Este é basicamente um adendo para Nikolay R's responda. Ele já cobriu algumas das sugestões listadas no artigo.

Nota: O artigo faz parte da documentação do BizTalk, mas pode se aplicar a qualquer coisa usando o MSDTC.

"Se você estiver usando a estrutura da entidade com transações, o Entity Framework abre e fecha automaticamente uma conexão com cada chamada de banco de dados. Portanto, ao usar transações, você está tentando espalhar uma transação por várias conexões. Isso se eleva ao MSDTC".

Você pode passar no contexto do seu banco de dados para a classe ou função Callee em sua transação.

Talvez esta seja a sua resposta: Erro do MSSQL 'O provedor subjacente falhou em aberto'

Supressing a transação é útil se você pretende executar algum código que pode falhar, mas que você não quer abortar a transacção por causa do que falha.

A pergunta que você precisa se perguntar é o seguinte:Tem acesso a mais de 1 durável recurso em seu transactionScope?Quero dizer, você abrir conexões para mais de 1 DB?

Esta é uma questão importante como a transação será encaminhado para o DTC se você acessar mais de 1 durável de recursos.

Pelo menos dois durável recursos que suportam fase única notificações inscrito na transacção.Por exemplo, inscrevendo-se para uma única conexão com a não causar uma transação para ser promovido.No entanto, sempre que você abre uma segunda conexão para um banco de dados fazendo com que o banco de dados para inscrever-se, o Sistema.Transações de infra-estrutura detecta que ele é o segundo durável de recursos na transação, e aumenta-o para uma transação MSDTC. Fonte: MSDN

Se for esse o caso, você pode resolver o seu problema através do aninhamento de seu transactionscopes corretamente, exemplo:

//Create rootScope
using(TransactionScope rootScope = new TransactionScope()) 
{ 
    using(TransactionScope scope2 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB1
         ...

         //Complete this ambient transaction
         scope2.Complete();
    } 

    using(TransactionScope scope3 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB2
         ...

         //Complete this ambient transaction
         scope3.Complete();
    } 

    //Complete rootScope
    //The whole transaction will only be committed if you call 
    //Complete on the rootScope
    rootScope.Complete();

}

Você pode encontrar mais informações sobre TransactionScopes, como aninhamento de obras,...no MSDN.

Espero que essa resposta pode ajudar as pessoas no futuro.

Se o serviço de coordenador de transação distribuído não for iniciado, a Entidade Framework não poderá se conectar ao banco de dados. Abra e inicie o coordenador de transações distribuídas

Serviços -> Coordenador de transações distribuído

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top