2009-10-09 19 views
6

¿Es posible utilizar los System.Transactions modelo de programación sin soporte para transacciones distribuidas?.NET: ¿cómo desactivar la promoción en System.Transactions?

algo así como

TransactionConfig.DisablePromotion = true; 
+0

¿Qué problema tienes al querer deshabilitar la promoción? –

+0

Uso un servidor vinculado para conectar dos servidores Sql. Para la lógica del servidor vinculado, he usado transacciones explícitas, por lo que la integridad está bien. Pero cuando termino con el servidor vinculado SQL Server no libera la conexión interna. Cuando mi aplicación continúa y utiliza transacciones implícitas (por simplicidad), siempre se ejecutan en UNA base de datos. Pero la promoción se produce porque la conexión del servidor vinculado todavía está abierta. – andreas

Respuesta

10

No, no se puede desactivar la promoción de transacción a través de una propiedad o de configuración. La única forma de deshabilitar la promoción de transacciones es evitar las condiciones que hacen que la transacción se promueva a una transacción distribuida.

Para evitar transaction management escalation es necesario:

  • tiene SQL Server 2005 o superior como su base de datos

  • si SQL Server 2005, utilice sólo una conexión de base de datos para la duración de la transacción . (SQL Server 2008 le permitirá utilizar múltiples conexiones dentro de una transacción sin que se produzca la promoción.)

  • acceso de sólo una base de datos

  • no pase su transacción a través de dominios de aplicación


El motivo de las reglas es garantizar el ACID properties de la transacción.

Como ejemplo, supongamos por un minuto que podría especificar no promover una transacción (como en su fragmento de código) pero su código accede a dos bases de datos (sé que su código solo usa una base de datos). Entonces, ahora que ha especificado no usar transacciones distribuidas, ha iniciado una transacción y ha especificado que dos bases de datos deben estar dentro de esa unidad de trabajo. Existe un conflicto entre las propiedades ACID de la transacción y el deseo de evitar una transacción distribuida. Me parece que habría dos maneras de manejar esta situación: o bien la promoción de la transacción para una transacción distribuida (que habías dicho que no quiere hacer!) O lanzar una excepción (ya que no puede garantizar la integridad de la transacción).

lo tanto, el uso de una propiedad DisablePromotion no tendría mucho valor ya que, para que la aplicación no promueve la transacción, que todavía tienen que seguir las reglas de escalado.

Si realmente quería, se podía controlar el evento DistributedTransactionStarted y lanzar una excepción cuando se inicia una transacción distribuida. Eso garantizaría que su aplicación no esté utilizando transacciones distribuidas, pero que probablemente no sea lo que desea.

+2

+1 para ti Tuzo. Bien dicho. –

+1

Si su transacción se está promocionando porque está accediendo a dos bases de datos, pero solo está * escribiendo * en una base de datos, es posible que evite la promoción al suprimir la transacción al acceder a la otra base de datos. es decir, 'using (new TransactionScope (TransactionScopeOption.Suppress, new TransactionOptions {IsolationLevel = IsolationLevel.ReadUnCommitted})) {// Acceso a otro db}' –

2

No creo que hay una manera directa desactivar promoción. Es posible que desee ver las situaciones que hacen que una transacción sea promovida. Juval Lowy escribió un excelente whitepaper (también descargable here) todo sobre System.Transactions. Él cubre las reglas de promoción en detalle.

+0

También puede encontrar una versión HTML del Sistema introductorio de Juval Lowy.Transacciones en http://msdn.microsoft.com/en-us/library/ms973865.aspx –

+0

Excelente libro blanco. Muchas gracias. – Maarten

1

estoy usando el siguiente código con el servicio MSDTC desactivado.

var txOpts = new TransactionOptions 
      { 
      IsolationLevel = IsolationLevel.ReadCommitted, 
      Timeout = TimeSpan.FromMinutes(10)}; 

using (var tx = new TransactionScope(TransactionScopeOption.Suppress, txOpts)) 
{ 
    using (var db1 = new ObjectContext(connection1)) 
    { 
    db1.Connection.Open(); 
    using (var db1tx = db1.Connection.BeginTransaction(
           System.Data.IsolationLevel.ReadCommitted)) 
    { 
     using (var db2 = new ObjectContext(connection2)) 
     { 
     db2.Connection.Open(); 
     using (var db2tx = db2.Connection.BeginTransaction(
          System.Data.IsolationLevel.ReadCommitted)) 
     { 
      // do stuff 

      db1.SaveChanges(false); 
      db2.SaveChanges(false); 

      db1tx.Commit(); 
      db2tx.Commit(); 
      tx.Complete(); 
     } 
     } 
    } 
    } 
} 
Cuestiones relacionadas