5

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

using (DbTransactio txn = cnctn.BeginTransaction())

这有什么原因吗?

4

2 回答 2

6

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

在这种特定情况下,答案是:因为在发生错误时,您希望事务回滚而不是留给 GC。就个人而言,我可能倾向于使用catchto Rollback,但应该希望已经这样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();
}
于 2013-01-25T10:21:34.207 回答
5

如果你有这样的代码:

DbTransactio txn = cnctn.BeginTransaction();

// do something which throws an exception

txn.Commit();

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

你当然可以这样做:

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()用来回滚事务。

于 2013-01-25T10:21:27.407 回答