3

大家好,我们已经开始使用事务范围,下面是代码片段。我们需要了解的是基于我们在每次使用连接后的理解,特定连接将被释放/关闭对吗?那么自从它关闭以来,transaction.complete 是如何工作的呢?

using (TransactionScope transScope = new TransactionScope())
{
   try
   {
      string myConnStringLocal = "User Id=***;Password=****;Host=" + globalSettings.settingLocalIP + ";Database=" + globalSettings.settingLocalDB;
      using (MySqlConnection connectionLocal = new MySqlConnection(myConnStringLocal))
      {
         try{
         connectionLocal.Open();
         }
         Catch(Exception e)
         {

         }
         finally{
         connectionLocal.Close();
         }
      }

      string myConnStringCentral = "User Id=***;Password=*****;Host=" + globalSettings.settingCentralIP + ";Database=" + globalSettings.settingCentralDB;
      using (MySqlConnection connectionCentral = new MySqlConnection(myConnStringCentral))
      {
         try{
         connectionCentral.Open();
         }
         Catch(Exception e)
         {

         }
         finally{
         connectionCentral.Close();
         }

      }
      string myConnStringCentralCopy = "User Id=*****;Password=*****;Host=" + globalSettings.settingCentralCopyIP + ";Database=" + globalSettings.settingCentralCopyDB;
      using (MySqlConnection connectionCentralCopy = new MySqlConnection(myConnStringCentralCopy))
      {
         try{
         connectionCentralCopy.Open();
         }
         Catch(Exception e)
         {

         }
         finally{
         connectionCentralCopy.Close();
         }
      }
      transScope.Complete();
      Console.WriteLine("Transaction is completed");
   }
   catch (Exception)
   {
      Console.WriteLine("Transaction is rolled back");
   }
}
4

3 回答 3

7

TransactionScope.Complete告诉所有事务管理器他们可以提交这个事务。这并不能保证一切都会实际提交。调用Complete方法后,所有事务管理器都单独启动提交,如果所有事务管理器都成功,则认为事务成功完成。您可以参考此链接了解更多详情

于 2013-07-29T03:44:41.987 回答
4

When you connect to multiple databases in a single TransactionScope, the transaction is escalated to a distributed transaction and coordinated by MSDTC using 2-phase commit.

Regarding connection close - this is special case when connection is closed inside a TransactionScope, internally it is managed by System.Transactions infrastructure, so db session may still be open even though connection closed from your end.

See this note on MSDN:

Pending transactions started using Transact-SQL or BeginTransaction are automatically rolled back when the connection is reset if connection pooling is enabled. If connection pooling is off, the transaction is rolled back after SqlConnection.Close is called. Transactions started through System.Transactions are controlled through the System.Transactions infrastructure, and are not affected by SqlConnection.Close

EDIT Based on your comments, here is what you can do:

try
{
   using (TransactionScope transScope = new TransactionScope())
   {
      string myConnStringLocal = ...;
      using (var connectionLocal = new MySqlConnection(myConnStringLocal))
      {
         connectionLocal.Open();
         // do your DB update 

      } //no need to close connection explicitly, the using() {..} statement does that for you

      string myConnStringCentral = ...;
      using (var connectionCentral = new MySqlConnection(myConnStringCentral))
      {
         connectionCentral.Open();
         // do your DB update

      } //no need to close connection explicitly, the using() {..} statement does that for you

      string myConnStringCentralCopy = ...;
      using (var connectionCentralCopy = new MySqlConnection(myConnStringCentralCopy))
      {         
         connectionCentralCopy.Open();
         // do your DB update

      } //no need to close connection explicitly, the using() {..} statement does that for you

      transScope.Complete();

      Console.WriteLine("Transaction is completed");

   } //no need to dispose transactionScope explicitly, the using() {..} statement does that for you
}
catch (Exception)
{
      // If any exception occurs in the try block above transScope.Complete() line will be caught here
      // and will automatically cause the transaction to rollback.
      Console.WriteLine("Transaction is rolled back");
}

// You can then start new TransactionScope if you want to further update more than one DB in a transactional manner.
try
{
   using (TransactionScope transScope = new TransactionScope())
   {
      //...

   }
}
catch (Exception)
{
     //...
}
于 2013-07-29T06:10:15.943 回答
2

When the Complete method is called, then everything in the scope will be committed, if no Exception is thrown. If the code gets out of scope without Complete, then no commit will occur. In short, if you call the Complete method, then, in case there are no Exceptions thrown, your transaction(s) in the scope of the given TransactionScope will be committed.

Also, I must add, that there might also be a hierarchy, a tree of TransactionScopes. You can also set the behavior of a TransactionScope for the case when a sub-scope of the TransactionScope rolled back.

于 2013-07-29T05:39:41.697 回答