代码之家  ›  专栏  ›  技术社区  ›  Scott Munro Shimmy Weitzhandler

为什么TransactionScope不假定成功?

  •  10
  • Scott Munro Shimmy Weitzhandler  · 技术社区  · 16 年前

    TransactionScope希望调用其Complete方法,如下所示。否则事务将不会提交。

    using(TransactionScope scope = new TransactionScope())
    {
        /* Perform transactional work here */
    
        scope.Complete();
    }
    

    如果出现异常或调用“回滚”等方法(此方法当前不存在),则可以回滚事务。

    using(TransactionScope scope = new TransactionScope())
    {
        /* Perform transactional work here */
    
         if(problemOccurred)
         {
             scope.Rollback();
         }
    }
    

    请注意,ProblemOccursed标志仅在问题未导致异常的情况下才需要。在这种情况下,将自动执行回滚。

    我有兴趣进一步了解为什么使用此实现。

    更新: 到目前为止,有几个答案认为,如果使用我描述的实现,则需要try-catch块。事实并非如此。当使用块中未处理异常时,事务将自动回滚。现有的实现和我描述的实现都是这样。请参阅“完成事务范围”一节 here 详情请参阅。

    更新2: 我终于明白了答案中的解释。这不是一个可以被语言设计者认为合适的任何方式解释的语言构造——它是IDisposable模式的实现。如果不调用Dispose方法来完成代码,则不知道调用它是因为using块中的代码成功执行还是因为发生异常。我想象着类似于下面的事情,其中transaction和rollback都是关键字。

    transaction
    {
        /* Perform transactional work here */
    
         if(problemOccurred)
         {
             rollback;
         }
    }
    

    如果需要将事务选项传递给TransactionScope,这当然会出现问题。

    4 回复  |  直到 16 年前
        1
  •  14
  •   Jon Skeet    16 年前

    这意味着您不需要为失败案例添加手动try/finally(或catch)块(可能带有“success”标志)。试着重写上面的代码以在出错时回滚,看看它有多混乱。。。

    基本上,正常的期望行为是仅在到达块末尾时提交,没有异常。实现这一点的最简单方法是在块的末尾放置一个表示成功的方法调用。

        2
  •  15
  •   Stefan Steinegger    16 年前

    using(TransactionScope scope = new TransactionScope())
    {
      try
      {
        /* Perform transactional work here */
      }
      catch (Exception)
      {
        scope.Rollback();
        throw;
      }
    }
    

    这是更多的代码。

    编辑:

    其他一切都是危险的或糟糕的风格。 您必须绝对确保在提交时没有任何错误 Complete 你知道。

    . 只需在没有任何特殊错误处理的情况下实现事务,并在最后提交它。当发生任何错误时,您不必关心和回滚。考虑,异常几乎可以在每一行代码中抛出(eg. NullReference、溢出、无效操作等)。那么还有什么比这更容易的呢?

        3
  •  4
  •   David M    16 年前

    但是,严肃地说,设计用于防止部分或不正确更新的机制中的默认行为肯定必须是 承诺,不是吗?

        4
  •  3
  •   tvanfosson    16 年前

    我认为,正如@Jon Skeet所说,为成功而编写的代码数量比目前的方式要少(也不那么难看)。然而,从交易的角度来看,我认为你会 希望 保持悲观,并假设除非明确指出成功,否则你会将其退回。在我看来,错误地提交事务比由于代码错误而意外地未能提交成功的事务要糟糕得多。