【问题标题】:Understanding how transaction.complete function?如何理解transaction.complete函数?
【发布时间】:2013-07-28 17:59:36
【问题描述】:

大家好,我们已经开始使用事务范围,下面是代码 sn-p。我们需要了解的是基于我们在每次使用连接后的理解,特定连接将被释放/关闭对吗?那么自从它关闭后,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");
   }
}

【问题讨论】:

  • 您是否尝试过实际运行代码并查看发生了什么?
  • @是的,我尝试了交易,但我想了解它的细节。

标签: c# distributed-transactions


【解决方案1】:

TransactionScope.Complete 告诉所有事务管理器他们可以提交这个事务。这并不能保证一切都会实际提交。在调用 Complete 方法后,所有事务管理器都单独启动提交,如果所有事务管理器都成功,则认为事务成功完成。 你可以参考这个link for further details

【讨论】:

  • @So 我的终极目标是如何保证所有人都会承诺?我的意思是在这些情况下如何确保分布式事务的完整性?所以在每次使用结束后连接都没有关闭,那么它将如何调用连接呢?
  • 你永远不能保证提交。事务的目的不是保证一切都会发生,而是保证一切都会提交或什么都不会提交。
  • @So 它保证不会有任何一次提交,要么全部提交,要么完全不提交。那么 using 块之后的连接可用性如何?
  • @YK1 对连接可用性有很好的解释。
【解决方案2】:

当您在单个TransactionScope 中连接到多个数据库时,事务将升级为distributed 事务并由MSDTC 使用2-phase commit 进行协调。

关于连接关闭 - 这是在 TransactionScope 内关闭连接时的特殊情况,在内部它由 System.Transactions 基础设施管理,因此即使连接从您端关闭,数据库会话仍可能打开。

MSDN上查看此注释:

如果启用了连接池,则在重置连接时会自动回滚使用 Transact-SQL 或 BeginTransaction 启动的待处理事务。如果连接池关闭,则在调用 SqlConnection.Close 后回滚事务。通过 System.Transactions 启动的事务通过 System.Transactions 基础结构进行控制,不受 SqlConnection.Close 影响

编辑根据您的 cmets,您可以执行以下操作:

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)
{
     //...
}

【讨论】:

  • 是的,这就是我正在寻找的原因,如果您看到我的问题,我已经通过 try 和 catch 进一步更新它,最后单独关闭连接。可以吗?您能否查看我的问题中的代码,这样做是否正确?
  • @new14:如果您有using( .. myconn... ) { .. } ,则无需在finally 块中显式关闭连接 - 因为using 语句编译为try/finally 块并调用Dipose on finally 块中的连接自动 - Dispose 反过来将调用 Close
  • try/finally 的编译在哪里,因为我们看不到它在后台?我这里不太清楚,请进一步描述。
  • @new14:请了解using 语句的工作原理。 codeproject.com/Articles/6564/… 在您的情况下,连接对象的 Dispose() 将调用其 Close(),因此您不必显式调用它。
  • @new14:我上面链接的代码项目文章有一个小错误 - 它说The CLR converts your code into MSIL 这是不正确的。它实际上是 C# 编译器。
【解决方案3】:

当调用Complete 方法时,如果没有抛出Exception,则范围内的所有内容都将被提交。如果代码在没有Complete 的情况下超出范围,则不会发生提交。简而言之,如果您调用Complete 方法,那么,如果没有Exceptions 抛出,您在给定TransactionScope 范围内的事务将被提交。

另外,我必须补充一点,可能还有一个层次结构,TransactionScopes 的树。您还可以为TransactionScope 的子范围回滚的情况设置TransactionScope 的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2015-02-04
    相关资源
    最近更新 更多