【发布时间】:2013-01-25 10:12:24
【问题描述】:
我了解隐式回滚(通常在发生异常并调用 Dispose 时发生)并不能保证所有提供程序。然而,许多示例使用:
using (DbTransactio txn = cnctn.BeginTransaction())
有什么原因吗?
【问题讨论】:
标签: c# ado.net transactions system.data
我了解隐式回滚(通常在发生异常并调用 Dispose 时发生)并不能保证所有提供程序。然而,许多示例使用:
using (DbTransactio txn = cnctn.BeginTransaction())
有什么原因吗?
【问题讨论】:
标签: c# ado.net transactions system.data
最简单的答案是“因为它实现了IDisposable”。任何实现IDisposable 的类型:适当地处理它是你的工作。在这种情况下,使用过程代码,最简单的方法是通过 using 语句。
在这种特定情况下,答案是:因为在发生错误时,您希望事务回滚而不是留给 GC。就我个人而言,我可能倾向于使用catch 到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();
}
【讨论】:
Dispose() 仅仅因为它是IDisposable。根据我的示例,我同意在这种情况下我更喜欢明确的Rollback()。但这是对Dispose() 的添加,而不是代替。
如果你有这样的代码:
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,则无需显式调用Rollback。恕我直言,代码更干净,有一个带有Commit() 的 using 块。