2009-10-23 32 views
5

en nuestro proyecto actual, estamos utilizando ADO.NET Entity Framework como capa de datos para la aplicación. Hay algunas tareas que requieren ejecutarse en una transacción porque hay mucho trabajo por hacer en la base de datos. Estoy usando un TransactionScope para rodear esas tareas.Problema de MSDTC con transacciones en ADO.NET Entity Framework

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

El problema es tan pronto como estoy usando un TransactionScope se produce una excepción:

System.Data.EntityException: El proveedor subyacente falló en Abrir. ---> System.Transactions.TransactionManagerCommunicationException: la comunicación con el administrador de transacciones subyacente ha fallado. ---> System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL ha sido devuelto desde una llamada a un componente COM.

Parece que este error tiene que ver con el MSDTC (Coordinador de transacciones distribuidas de Microsoft). Cuando cambio la configuración de seguridad de MSDTC se lanza otra excepción:

System.Data.EntityException: El proveedor subyacente falló en Abrir. ---> System.Transactions.TransactionManagerCommunicationException: Se ha deshabilitado el acceso a la red para Distributed Transaction Manager (MSDTC). Habilite DTC para el acceso a la red en la configuración de seguridad para MSDTC utilizando la herramienta administrativa de Servicios de componentes.

Sin embargo, MSDTC está configurado, el TransactionScope causará un error. ¿Alguien sabe qué está yendo mal aquí?

Respuesta

-2

Hmm, parece que funciona cuando cambio el TransactionScopeOption "suprimir":

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

¿Todos saben por qué?

+4

Creo no utiliza ninguna transacción en este caso, pero no estoy seguro. –

+0

Sí, esta opción indica que no debe participar en la transacción. –

+1

Recibo el mismo error, pero no hay forma de que sea la mejor respuesta. –

7

De manera predeterminada, MSDTC tiene acceso a la red deshabilitado. Para conseguir que funcione hay que ir a

Panel de control-> Administrativo Herramientas-> Componente Servicios-> Componente Serivces-> Computes-> Mi PC> Derecho click-> Propiedades-> MSDTC-> seguridad configuración

y comprobar siguientes casillas de verificación DTC desde la red de acceso, Permitir entrantes, Permitir salientes. La autentificación se debe elegir según su entorno. También es posible que desee echar un vistazo a la herramienta DTCPing para depurar transacciones distribuidas. Para darle un acceso directo - es posible que tenga que modificar se registro:

HKLM \ Software \ Policies \ Microsoft \ Windows NT \ RPCRestrictRemoteClients = 0 HKLM \ Software \ Policies \ Microsoft \ Windows NT \ RPCEnableAuthEpResolution = 1

para poner todo en funcionamiento.

+0

, gracias, herramienta DTCPing me dijeron que hay algunos errores de puntos finales RPC. Ahora estoy revisando http://support.microsoft.com/kb/306843 y http://support.microsoft.com/kb/839880/EN-US/ tal vez esa es la solución. – Alexander

+0

Para Windows 8, la "Configuración de seguridad" se puede encontrar aquí: http://stackoverflow.com/questions/7694/how-do-i-enable-msdtc-on-sql-server/27263904#27263904 –

0

Esto significa que está suprimiendo cualquier transacción que pueda estar vigente actualmente cuando ingresa su bloque de código, por lo que las actualizaciones que haga su código no se revertirán si la transacción "ambiente" externa decide deshacerse.

0

este es el artículo que se utilizó en la resolución de nuestro propio tema, de forma similar:

Troubleshooting Problems with MSDTC

Ésta es básicamente una adición al Nikolay R's respuesta. Él ya cubrió algunas de las sugerencias enumeradas en el artículo.

Nota: El artículo es parte de la documentación de Biztalk, pero se puede aplicar a cualquier cosa que use MSDTC.

+0

Actualizado similar artículo http://msdn.microsoft.com/en-us/library/aa561924.aspx – JeremyWeir

3

Sí, funciona usando Supress, porque le está diciendo que suprima o ignore la transacción ambiental y cree una nueva transacción local. Dado que la transacción es local, no se trata de una transacción distribuida, por lo que no está utilizando MSDTC, pero es probable que no deba utilizar Suprimir y debería utilizar Obligatorio en su lugar.

0

"Si está utilizando Entity Framework con Transacciones, Entity Framework se abre y cierra automáticamente con cada llamada a la base de datos. Por lo tanto, cuando usa transacciones, intenta distribuir una transacción a través de múltiples conexiones.

Puede pasar el contexto de su base de datos para llamar a la clase o función en su transacción.

Tal vez este es su respuesta: MSSQL Error 'The underlying provider failed on Open'

0

suprimiendo la transacción es muy útil si desea ejecutar un código que puede fallar, pero que no quieren abortar la transacción debido a que fallan.

La pregunta que debe hacerse es la siguiente: ¿Está accediendo a más de 1 recurso duradero en su transactionScope? Quiero decir, ¿abres conexiones a más de 1 DB?

Esta es una pregunta importante ya que la transacción se escalará hacia DTC si accede a más de 1 recurso duradero.

Al menos dos recursos duraderos que admiten notificaciones monofásicas se alistan en la transacción. Por ejemplo, alistar una sola conexión con no causa que se promueva una transacción. Sin embargo, cada vez que abre una segunda conexión a una base de datos que hace que la base de datos se aliste, la infraestructura System.Transactions detecta que es el segundo recurso duradero en la transacción y lo escala a una transacción MSDTC. Fuente: MSDN

Si ese es el caso, puede resolver su problema por los nidos de sus transactionscopes correctamente, ejemplo:

//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(); 

}

Puede encontrar más información sobre TransactionScopes, cómo funciona la anidación , ... en MSDN.

Espero que esta respuesta pueda ayudar a las personas en el futuro.

0

Si no se inicia el servicio del Coordinador de transacciones distribuidas, el marco de la entidad no se puede conectar a la base de datos. abrirá y comenzará el Coordinador de transacciones distribuidas

Servicios - Coordinador de transacciones> Distributed

Cuestiones relacionadas