为什么TransactionScope不能成功?

时间:2010-01-04 13:15:24

标签: .net transactionscope

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

请注意,只有在问题没有导致异常的情况下才需要使用problemOccurred标志。在这种情况下,回滚将自动执行。

我有兴趣进一步了解为何使用此实施。

更新:到目前为止,有几个答案认为如果使用我所描述的实现,则需要一个try-catch块。不是这种情况。在using块中未处理异常时,将自动回滚事务。在现有实现和我描述的实现中都是这种情况。有关详细信息,请参阅“完成交易范围”部分here

更新2:我终于明白了答案中的解释。这不是一种语言结构,它可以被任何语言设计者认为合适的方式解释 - 它是IDisposable模式的一种实现。如果没有调用Complete,Dispose方法中的代码就不知道是否因为使用块中的代码被成功执行或者因为发生了异常而被调用。我想象的事情类似于以下内容,其中事务和回滚都是关键字。

transaction
{
    /* Perform transactional work here */

     if(problemOccurred)
     {
         rollback;
     }
}

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

4 个答案:

答案 0 :(得分:15)

这样,每个交易都是这样的:

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

哪个代码更多。

修改

其他一切都是冒险或糟糕的风格。 您必须绝对确定提交时没有任何错误。离开使用块时,您不知道是否因为抛出异常或刚刚到达它的末尾而离开它。致电Complete时,您知道。

事务块语法已经是最简单的。只需在没有任何特殊错误处理的情况下实现事务,并在最后提交它。发生任何错误时,您无需关心和回滚。考虑一下,几乎每一行代码都会抛出异常(例如NullReference,Overflows,InvalidOperation等)。那么比这更容易呢?

答案 1 :(得分:14)

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

基本上,正常的期望行为是仅在到达块的末尾时才提交,没有例外。实现这一目标的最简单方法是在块结束时进行方法调用以表示成功。

答案 2 :(得分:4)

如果选择了其他实施,那么人们会问相反的问题!

严重的是,用于防止部分或不正确更新的机制中的默认行为肯定必须才能提交,不是吗?

答案 3 :(得分:3)

我认为,成功编写的代码量正如@Jon Skeet所说,当前的方式更少(而且不那么难看)。但是,从交易的角度来看,我认为你会想要悲观,并认为除非明确表示成功,否则你会将其回滚。在我看来,提交错误的事务是一个更糟糕的问题,而不是由于代码错误意外地无法提交成功的事务。