明确的交易回滚是否必要?

时间:2010-02-17 13:24:30

标签: c# sql database ado.net transactions

许多例子都提倡明确回滚数据库事务,其中包括:

using (var transaction = ...)
{
    try
    {
        // do some reading and/or writing here

        transaction.Commit();
    }
    catch (SqlException ex)
    {
        // explicit rollback
        transaction.Rollback();
    }
}

但是,我倾向于这样做:

using (var transaction = ...)
{
    // do some reading and/or writing here

    transaction.Commit();
}

当发生异常时,我只是依赖于未提交的事务的隐式回滚。

是否存在依赖此隐式行为的问题?有没有人有一个令人信服的理由为什么我不应该这样做?

5 个答案:

答案 0 :(得分:14)

不,它并非特别需要,但我可以想到它可能是一个好主意的两个原因:

  • 净度

有些人可能会争辩说,使用transaction.Rollback()可以在什么情况下更清楚地提交交易。

  • 释放锁

在处理事务时,重要的是要意识到某些锁只会在事务回滚或提交时释放。如果您正在使用using语句,则事务将在事务处理时回滚,但是如果由于某种原因您需要在using块内部进行一些错误处理,则可能是有利的在执行复杂/耗时的错误处理之前回滚事务(删除锁)。

答案 1 :(得分:4)

我发现您的使用存在两个问题:

  1. 您依赖事务的Dispose()方法来回滚未提交的事务,从而创建对第三方IDisposable实现的依赖。在这种情况下,这当然是一个可以忽略不计的风险,但不是一个好的做法。
  2. 您错过了记录和/或处理异常的机会。另外,我会捕获Exception而不是SqlException。

答案 2 :(得分:1)

我想可以回答第一种方法对于维护代码的人来说更具可读性。编码的明确性使得目标明确且快速。虽然隐式回滚对您来说很明显,并且可能是任何拥有超过事务处理知识的人,但它可能不属于其他人。也就是说,一些评论很快就会纠正这一点。唯一的问题是隐式回滚是否是对象的文档特征。

所以,我会说,如果您对操作发表评论,并且可以依赖隐式操作,那么就没有充分的理由去采用明确的方法。

答案 3 :(得分:1)

大多数正确编写的ADO.NET连接都会回滚未显式提交的事务。所以这不是绝对必要的。

我看到显式Rollback()的主要好处是它能够在那里设置断点,然后检查连接或数据库以查看发生了什么。对于未来的代码维护者来说,在不同的执行路径下发生的事情也更加清晰。

答案 4 :(得分:0)

只要事务在using()块中完全自包含,你就可以了。但是,如果有人从调用方传递现有的事务对象,则可能会出现问题。但那是另一种情况......