2011-10-31 141 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(); 
        } 
    }