是否需要显式事务回滚?

发布于 2024-08-21 20:43:23 字数 520 浏览 6 评论 0原文

许多例子都主张显式回滚数据库事务,大致如下:

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

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

依赖这种隐式行为有什么问题吗?有人有一个令人信服的理由为什么我不应该这样做吗?

Many examples out there advocate explicit rollback of database transactions, along the lines of:

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

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

However, I tend to do this:

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

    transaction.Commit();
}

When an exception occurs, I'm just relying on the implicit rolling back of transactions that aren't committed.

Is there any problem relying on this implicit behavior? Does anyone have a convincing reason why I shouldn't be doing it this way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

巴黎夜雨 2024-08-28 20:43:23

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

  • 清晰度

有些人可能会认为使用 transaction.Rollback() 可以更清楚地表明在什么情况下事务不会发生尽心尽力。

  • 释放锁

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

No, its not specifically needed, however I can think of 2 reasons why it might be a good idea:

  • Clarity

Some might argue that using transaction.Rollback() makes it clearer under what circumstances the transaction will not be committed.

  • Releasing locks

When dealing with transactions it is important to realise the certain locks will only be released when the transaction is rolled back or committed. If you are using the using statement then the transaction will be rolled back when the transaction is disposed of, however if for some reason you need to do some error handling inside the using block, it may be advantageous to rollback the transaction (removing the locks) before performing complex / time consuming error handling.

不知在何时 2024-08-28 20:43:23

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

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

Most properly written ADO.NET connection will rollback transactions not explicitly committed. So it's not strictly necessary.

The main benefit I see of an explicit Rollback() call it the ability to set a breakpoint there and then inspect either the connection or the database to see what was going on. It's also clearer to future maintainers of the code what happens under different execution paths.

还给你自由 2024-08-28 20:43:23

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

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

I see two problems with your usage:

  1. You're relying on the transaction's Dispose() method to rollback an uncommitted transaction, creating a dependency on a third-party's implementation of IDisposable. It's a negligible risk in this case of course but not a good practice.
  2. You are missing the opportunity to log and/or handle the exception. Also, I would catch Exception not SqlException.
谷夏 2024-08-28 20:43:23

我想可以回答说,第一种方法对于维护代码的人来说更具可读性。编码的明确性质使得目标清晰且快速。虽然隐式回滚对于您以及可能对事务处理有更多了解的任何人来说都是清楚的,但对其他人来说可能并不清楚。也就是说,一些评论很快就能纠正这个问题。唯一的问题是隐式回滚是否不是对象的已记录功能。

因此,我想说,如果您对操作进行评论并且可以依赖隐式操作,那么就没有充分的理由采用显式方法。

I guess it could be answered that the first approach is more readable for someone maintaining your code. The explicit nature of the coding makes the objectives clear and quickly. While the implicit rollback is clear to you, and probably anyone who has more than a passing knowledge of the transaction handling, it may not be to others. That said, a few comments would quickly rectify that. The only concern is if the implicit rollback is not a documented feature of the object.

So, I'd say, providing you comment the operation and you can rely on the implicit action, then there's not a good reason to go for the explicit approach.

梨涡 2024-08-28 20:43:23

只要事务在 using() 块中完全独立,就可以开始了。但是,如果某人从调用者那里传递了现有的事务对象,那么问题可能而且确实会出现。但那是不同的场景...

As long as the transaction is totally self-contained in the using() block, you are good to go. Problems can and do arise, though, if someone if you are passed an existing transaction object from a caller. But that's a different scenario...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文