2011-10-31 14 views
7

Estamos tratando de hacer transacciones de anidación indirecta utilizando el código de abajo, .NET 3.5, SQL Server 2005. &usando TransactionScope: System.Transactions.TransactionAbortedException: La transacción se ha abortado

MSDN dice que cuando se utiliza TransactionScope, una transacción se escala cada vez que la aplicación abre una segunda conexión (incluso a la misma base de datos) dentro de la Transacción.

void RootMethod() 
{ 
    using(TransactionScope scope = new TransactionScope()) 
    { 
     /* Perform transactional work here */ 
     FirstMethod(); 
     SecondMethod(); 
     scope.Complete(); 
    } 
} 

void FirstMethod() 
{ 
    using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required)) 
    { 
    using (SqlConnection conn1 = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI")) 
     { 
    string insertString = @" 
      insert into Categories 
      (CategoryName, Description) 
      values ('Laptop1', 'Model001')"; 
     conn1.Open(); 
     SqlCommand cmd = new SqlCommand(insertString, conn1); 
     cmd.ExecuteNonQuery(); 
     } 
     scope.Complete(); 
    } 
} 

void SecondMethod() 
{ 
    using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required)) 
    { 
     using (SqlConnection conn2 = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI")) 
     { 
    string insertString = @" 
      insert into Categories 
      (CategoryName, Description) 
      values ('Laptop2', 'Model002')"; 

     conn2.Open(); //Looks like transactionabortedException is happening here 
     SqlCommand cmd = new SqlCommand(insertString, conn2); 
     cmd.ExecuteNonQuery(); 
     } 
     scope.Complete(); 
    } 
    } 

En ocasiones, la transacción falla que no está promoviendo a DTC, y estamos consiguiendo los siguientes como el seguimiento de la pila interna,

System.Transactions.TransactionAbortedException: The transaction has aborted. ---> 
System.Transactions.TransactionPromotionException: Failure while attempting to promote transaction. ---> 
System.InvalidOperationException: The requested operation cannot be completed because the connection has been broken.  
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)  
at System.Data.SqlClient.SqlDelegatedTransaction.Promote()  --- End of inner exception stack trace ---  
at System.Data.SqlClient.SqlDelegatedTransaction.Promote()  
at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)  
at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)  
--- End of inner exception stack trace ---  
at System.Transactions.TransactionStateAborted.CreateAbortingClone(InternalTransaction tx)  
at System.Transactions.DependentTransaction..ctor(IsolationLevel isoLevel, InternalTransaction internalTransaction, Boolean blocking)  
at System.Transactions.Transaction.DependentClone(DependentCloneOption cloneOption)  
at System.Transactions.TransactionScope.SetCurrent(Transaction newCurrent)  
at System.Transactions.TransactionScope.PushScope()  
at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption)  

Puede alguien por favor me ayude a averiguar la razón de esto ¿fracaso?

+0

¿Has intentado cerrar la conexión? A veces obtengo esos errores cuando la conexión ya está abierta. Puede ser que podría estar equivocado. –

+0

intenté agregar *; MultipleActiveResultSets = True * en la cadena de conexión –

Respuesta

0

puedo proponerles una mejor manera de lograr su objetivo. debe haber una sola transacción para 2 llamadas DB por conexión.

Debe ser como

using (SqlConnection conn1 = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI")) 
{ 
    using (conn1.BeginTransaction() 
    { 
     try 
     { 
      FirstMethod(Conn1); 
      SecondMethod(Conn2); 
     } 
     catch() 
     { 
     } 
    } 
} 
+3

No puede decir que esta es la mejor solución. ¿Qué sucede si no puede cambiar los métodos para aceptar la conexión? ¿Qué pasa si los métodos están en diferentes objetos? ¿Qué pasa si esos métodos ya tienen demasiados parámetros? Y esto también es feo. –

3

Si utiliza TransactionScope y usted:

  • abierta más de una conexión a una base de datos y
  • está conectando a un servidor SQL Server 2005 servidor

la transacción se escalará a DTC. Marque esta otra cuestión de forma: TransactionScope automatically escalating to MSDTC on some machines?

La solución es o bien:

  • uso de SQL Server 2008 o
  • Uso SqlTransaction en lugar de TransactionScope al igual que la primera respuesta sugiere:

    using (var conn = new SqlConnection(connectionString)) 
    { 
        using (var tx = conn.BeginTransaction()) 
        { 
         FirstMethod(conn); 
         SecondMethod(conn); 
         tx.Commit(); 
        } 
    } 
    
Cuestiones relacionadas