Anidada / Niño TransactionScope Rollback

Estoy tratando de anidar TransactionScopes (.NET 4.0) ya que anidaría Transacciones en SQL Server, sin embargo, parece que operan de manera diferente. Quiero que las transacciones de mi hijo puedan retrotraerse si fallan, pero permite que la transacción padre decida si comprometer / revertir toda la operación. El problema es cuando ocurre la primera finalización, la transacción se revierte. Me doy cuenta de que completar es diferente a comprometerse.

Un ejemplo muy simplificado de lo que estoy tratando de hacer:

static void Main(string[] args) { using(var scope = new TransactionScope()) // Trn A { // Insert Data A DoWork(true); DoWork(false); // Rollback or Commit } } // This class is a few layers down static void DoWork(bool fail) { using(var scope = new TransactionScope()) // Trn B { // Update Data A if(!fail) { scope.Complete(); } } } 

No puedo usar las opciones Suprimir o RequiresNew ya que Trn B depende de los datos insertados por Trn A. Si utilizo esas opciones, Trn B es bloqueado por Trn A.

¿Alguna idea de cómo conseguiría que funcionara, o si es posible utilizando el espacio de nombres System.Transactions?

Gracias

Probablemente no te va a gustar esta respuesta, pero …

Votar dentro de un scope nested

Aunque un ámbito nested puede unirse a la transacción ambiente del ámbito raíz, la invocación completa en el ámbito nested no tiene efecto en el ámbito raíz. Solo si todos los ámbitos desde el scope raíz hasta el último ámbito nested votan para comprometer la transacción, se comprometerá la transacción.

(A partir de la implementación de una transacción implícita utilizando el scope de la transacción )

Desafortunadamente, la clase TransactionScope no proporciona ningún mecanismo (que yo sepa) para separar unidades de trabajo. Es todo o nada. Puede evitar que se produzca una transacción en una unidad de trabajo específica mediante el uso de TransactionScopeOption.Suppress , pero probablemente no sea lo que desea, ya que entonces perdería atomicidad por lo que esté dentro de ese scope.

Solo hay una transacción “ambiental” cuando usa un TransactionScope . Una vez que se elimina un TransactionScope o se recostack sin que se haya ejecutado Complete , toda la transacción ambiental se retrotrae; eso es todo, se acabó el juego.

De hecho, SQL Server no admite en absoluto transacciones anidadas verdaderas, aunque es posible (aunque algo poco intuitivo) lograr el mismo resultado final con el uso apropiado de las instrucciones SAVE TRAN . Volver a implementar esta lógica como un Procedimiento almacenado (o varios de ellos) podría ser su mejor opción si requiere este comportamiento en particular.