transaction practices net mvc framework best begin asp entity-framework transactions msdtc

entity-framework - practices - savechanges entity framework



¿Cómo ejecutar dos contextos de Entity Framework dentro de TransactionScope sin MSDTC? (3)

Bueno, el problema es bastante fácil.

Si está utilizando el servidor SQL 2008, no debería tener ese problema porque tiene una transacción que se puede promocionar y, como .NET sabe que está utilizando el mismo almacén de persistencia (la base de datos), no lo promocionará a DTC ni lo confirmará como local. mirar en la transacción promovible con el servidor SQL 2008.

Por lo que sé, Oracle está trabajando en su controlador para admitir transacciones promocionables, pero no conozco el estado, el controlador MS Oracle no lo admite. http://www.oracle.com/technology/tech/windows/odpnet/col/odp.net_11.1.0.7.20_twp.pdf

Si está utilizando un controlador que no admite transacciones promocionables, es imposible que .NET use transacciones locales haciendo dos conexiones. Debe cambiar su arquitectura o convencer al administrador de la base de datos para instalar MSDTC.

Este problema no es fácilmente reproducible en un ejemplo simple aquí, pero se preguntaba si alguien tiene alguna experiencia y consejos, aquí está el problema:

  • usando Entity Framework
  • tiene muchos puntos en la aplicación donde (1) los datos se escriben en una tabla de entidades , por ejemplo, el Cliente, (2) los datos se escriben en la tabla de historial
  • Ambas acciones usan Entity Framework, sin embargo, usan diferentes contextos
  • estas acciones deben ser ambas en una transacción : es decir, si una no puede escribir, la otra no debe escribir, etc.
  • Puedo envolverlos con un TransactionScope,

Me gusta esto:

using (TransactionScope txScope = new TransactionScope()) { ... }

pero esto me da:

El Coordinador de transacciones distribuidas de Microsoft (MSDTC) está deshabilitado para las transacciones de red.

El administrador de nuestra base de datos me dijo que MSDTC está deshabilitado por elección y no se puede instalar .

Por lo tanto, estoy haciendo cambios tratando de crear mi propia EntityConnection con un MetadataWorkspace con la idea de que cada contexto usará la misma EntityConnection . Sin embargo, esto está demostrando que es casi imposible intentar que funcione, por ejemplo, actualmente continúo obteniendo el error anterior, aunque en teoría ambos contextos usan EntityConnection. Es difícil entender dónde / por qué Entity Framework requiere el MSDTC, por ejemplo.

¿Alguien ha recorrido este camino antes, tiene experiencia o ejemplos de código para compartir?


Creo que lo que debes hacer es forzar a tus contextos a compartir una única conexión de base de datos. Entonces podrá realizar estas dos operaciones en dos contextos diferentes en una sola transacción. Puede lograr esto pasando un objeto EntityConnection a los dos constructores de su contexto. Por supuesto, este enfoque requerirá que pase este objeto a métodos que actualicen la base de datos.

Recientemente hice un blogged sobre la creación de un ámbito de contexto de base de datos que facilitará el uso de múltiples contextos y transacciones de EF.


Tuve un problema similar con SQL 2008, Entity Framework.

Tenía dos marcos definidos (EF1 y EF2) pero usando cadenas de conexión idénticas a una base de datos de SQL 2008.

Recibí el error de MSDTC anterior, cuando uso "usos" anidados en ambos. por ejemplo, el código era así:

using (TransactionScope dbContext = new TransactionScope()) { using (EF1 context = new EF1()) { // do some EF1 db call using (EF2 context2 = new EF2()) { // do some EF2 db call } } dbContext.Complete(); }

No era tan simple como esto, porque estaba dividido en varios métodos, pero esta era la estructura básica de los "usos".

La solución era abrir solo uno usando a la vez. No hay error MTDSC, No es necesario abrir transacciones distribuidas en db.

using (TransactionScope dbContext = new TransactionScope()) { using (EF1 context = new EF1()) { // do some EF1 db call } using (EF2 context2 = new EF2()) { // do some EF2 db call } dbContext.Complete(); }