11

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

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

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

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

更新2:我终于明白答案中的解释了。这不是一种语言结构,可以以任何语言设计者认为合适的方式解释 - 它是 IDisposable 模式的实现。如果没有调用 Complete,Dispose 方法中的代码将不知道调用它是因为 using 块中的代码成功执行还是因为发生了异常。我在想像下面这样的东西,其中事务和回滚都是关键字。

transaction
{
    /* Perform transactional work here */

     if(problemOccurred)
     {
         rollback;
     }
}

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

4

4 回答 4

15

这样,每笔交易都将如下所示:

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

哪个是更多的代码。

编辑:

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

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

于 2010-01-04T13:18:07.533 回答
14

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

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

于 2010-01-04T13:17:33.850 回答
4

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

不过说真的,旨在防止部分或不正确更新的机制中的默认行为肯定是提交,不是吗?

于 2010-01-04T13:17:51.187 回答
3

正如@Jon Skeet 所说,我认为为成功而编写的代码量更少(也更少丑陋)当前的方式。但是,从事务的角度来看,我认为您会希望保持悲观,并假设除非明确表明成功,否则您会回滚。在我看来,错误提交事务比由于代码错误而意外未能成功提交事务要糟糕得多。

于 2010-01-04T13:26:47.913 回答