2011-10-31 176 views
7

我們正在嘗試使用下面的代碼,.NET 3.5,& SQL Server 2005中使用的TransactionScope:System.Transactions.TransactionAbortedException:該交易已中止

MSDN說使用的TransactionScope時做間接嵌套事務,每當應用程序在事務中打開第二個連接(甚至是同一個數據庫)時,事務就會升級。

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

偶爾,交易失敗的是,不促進到DTC,並且我們得到以下的內堆棧跟蹤,

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)  

任何人都可以請幫我找出這個原因失敗?

+0

你試過關閉連接嗎?有時候,當連接已經打開時,我確實會發生這樣的錯誤。可能是我可能是錯的。 –

+0

你有沒有試過在連接字符串中加入*; MultipleActiveResultSets = True * –

回答

0

我可以向你提出一個更好的方法來實現你的目標。 每個連接應該有一個針對2個數據庫調用的事務。

應該像

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

你不能說這是更好的解決方案。如果你不能改變接受連接的方法怎麼辦?如果這些方法在不同的對象中呢?如果這些方法已經有太多的參數呢?這也很醜陋。 –

3

如果您使用的TransactionScope你:

  • 超過開啓一個連接到數據庫,並
  • 被連接到SQL Server 2005服務器

該交易將升級爲DTC。檢查此其他等問題:TransactionScope automatically escalating to MSDTC on some machines?

的解決方案可以是:

  • 使用SQL Server 2008或
  • 使用的SqlTransaction代替的TransactionScope就像前回答提示:

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