【问题标题】:Why to use using statement on DbTransaction in ADO.NET / C#?为什么在 ADO.NET / C# 中对 DbTransaction 使用 using 语句?
【发布时间】:2013-01-25 10:12:24
【问题描述】:

我了解隐式回滚(通常在发生异常并调用 Dispose 时发生)并不能保证所有提供程序。然而,许多示例使用:

using (DbTransactio txn = cnctn.BeginTransaction())

有什么原因吗?

【问题讨论】:

    标签: c# ado.net transactions system.data


    【解决方案1】:

    最简单的答案是“因为它实现了IDisposable”。任何实现IDisposable 的类型:适当地处理它是你的工作。在这种情况下,使用过程代码,最简单的方法是通过 using 语句。

    在这种特定情况下,答案是:因为在发生错误时,您希望事务回滚而不是留给 GC。就我个人而言,我可能倾向于使用catchRollback,但应该希望Dispose() 已经这样做了。不过,我自己不会依赖它,除非它被记录在案。例如:

    using(var tran = conn.BeginTransaction()) {
        try {
            // do stuff...
            tran.Commit();
        } catch {
            tran.Rollback();
            throw;
        }
    }
    

    请注意,在 TransactionScope 的相关案例中,“Dispose() 不标记它已完成”是预期发出回滚信号的方式:

    using(var tran = new TransactionScope()) {
        // do stuff...
        tran.Complete();
    }
    

    【讨论】:

    • 感谢您的回答。我的意思是,除了调用 Rollback(在大多数/所有情况下)之外,Dispose 还会做其他事情吗?如果想在 catch 子句中使用 Rollback,是否有理由调用 Dispose?我认为明确调用回滚是更好的编码。那么对于已经提交/回滚的事务是否需要 Dispose?
    • 强烈建议@matti Dispose() 仅仅因为它是IDisposable。根据我的示例,我同意在这种情况下我更喜欢明确的Rollback()。但这是对Dispose()添加,而不是代替。
    • 谢谢。我认为这对我来说已经足够了:D 但正如我所说,我更喜欢显式回滚。这有点棘手,因为如果出现问题,交易将不再活跃。因此,您的代码示例引发了有关回滚的异常,并且丢失了原始原因。例如,MSDN 有一个示例,其中 catch 子句中的回滚位于附加的 catch 子句中......这绝对是荒谬的。
    【解决方案2】:

    如果你有这样的代码:

    DbTransactio txn = cnctn.BeginTransaction();
    
    // do something which throws an exception
    
    txn.Commit();
    

    在垃圾收集器决定收集事务对象之前,事务不会回滚(请注意,只有实现IDisposable 的类遵循dispose pattern,它才会工作)。

    你当然可以这样做:

    DbTransaction txn = cnctn.BeginTransaction();
    try
    {
        // do something which throws an exception
    
        txn.Commit();
    }
    finally  
    {
        txn.Dispose();
    }
    

    但它的可读性不如

    using (var txn = cnctn.BeginTransaction())
    {
        // do something which throws an exception
    
        txn.Commit();
    }
    

    编辑:

    我理解隐式回滚(通常在发生异常并调用 Dispose 时发生)并不能保证所有提供程序。

    我还没有看到一个不支持它的提供商。由于IDbTransaction 确实继承IDisposable,所有实现都应该使用Dispose() 来回滚事务。

    【讨论】:

    • 感谢您的回答。我明白 using 是什么意思,但是如果它所做的只是调用回滚,为什么还要调用 Dispose?
    • 如果您使用using,则无需显式调用Rollback。恕我直言,代码更干净,有一个带有Commit() 的 using 块。
    猜你喜欢
    • 2022-12-12
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2010-11-10
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    相关资源
    最近更新 更多