2011-10-31 13 views
7

Stiamo cercando di fare di nidificazione delle transazioni indiretta usando il codice seguente, NET 3.5, & SQL Server 2005.utilizzando TransactionScope: System.Transactions.TransactionAbortedException: L'operazione è stata interrotta

MSDN dice che quando si utilizza TransactionScope, una transazione viene escalation ogni volta che l'applicazione apre una seconda connessione (anche allo stesso database) all'interno della Transazione.

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

Di tanto in tanto, l'operazione non riesce, che non sta promuovendo a DTC, e stiamo ottenendo i seguenti come l'analisi dello stack interno,

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)  

Qualcuno può aiutarmi a capire il motivo di questa fallimento?

+0

Hai provato a chiudere la connessione? A volte ottengo tali errori, quando la connessione è già aperta. Potrebbe essere che potrei sbagliarmi. –

+0

hai provato ad aggiungere *; MultipleActiveResultSets = True * nella stringa di connessione –

risposta

0

posso proporvi un modo migliore per raggiungere il vostro obiettivo. dovrebbe esserci una singola transazione per 2 chiamate DB per connessione.

Dovrebbe essere come

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

Non si può dire che questa sia la soluzione migliore. Cosa succede se non è possibile modificare i metodi per accettare la connessione? Cosa succede se i metodi sono in oggetti diversi? Cosa succede se quei metodi hanno già troppi parametri? E anche questo è brutto. –

3

Se si utilizza TransactionScope e voi:

  • aperta più di una connessione ad un database e
  • si connette a uno SQL Server 2005 Server

la transazione verrà inoltrata a DTC. Controllare questa domanda altri SO: TransactionScope automatically escalating to MSDTC on some machines?

La soluzione è o:

  • Utilizzare SQL Server 2008 o
  • Uso SqlTransaction invece di TransactionScope, proprio come l'ex risposta suggerisce:

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