虽然我的假设似乎听起来很主观,但经过一些研究后,我发现找到喜欢假人Try/Catch
而不是使用Using statement进行IDbConnection/IDbTransaction
处理的开发人员并不罕见(关闭/提交/回滚)。
即使是一些经验最丰富的开发人员和一些新开发人员也是如此。我故意不会在StackOverflow或论坛链接上引用任何问题作为示例,因此人们不会被冒犯。从what I found开始,Using语句为safe to use(无双关语)。
它有什么问题吗?请考虑以下代码:
Public Sub Commit()
Dim cn As IDbConnection = {CREATE_CONNECTION}
Dim tran As IDbTransaction = Nothing
cn.Open()
Try
tran = cn.BeginTransaction
'run some queries here
tran.Commit()
Catch ex As Exception
If Not tran Is Nothing Then tran.Rollback()
Throw
Finally
cn.Close()
End Try
End Function
假设{CREATE_CONNECTION}
是创建连接的Sub
的占位符,具体取决于数据库供应商,根据所有可能的最佳实践编写,并且不需要进一步改进。
有没有理由不能重写上述代码:
Using cn As IDbConnection = {CREATE_CONNECTION}
cn.Open()
Using tran As IDbTransaction = cn.BeginTransaction
'run some queries here
tran.Commit()
End Using
End Using
吗
显然,版本#2对它正在做的事情更直观。但也许我错过了一些重要的东西?像供应商特定的数据访问库实现那些内部不会在Transaction.Commit
上调用Connection.Close
和/或Dispose
的东西?这种方法在不久的将来会退役,还是在现代编程模式/最佳实践中不被视为足够清晰?单声道/移动应用开发工具缺少Using
关键字的调试支持?
我正在寻找支持或否认这一观点的任何答案。最好是带有原始文档引用的那个,如Do not use Using with IDbTransaction when ...
。博客或个人经历的链接也可以。
答案 0 :(得分:17)
我完全和你在一起;应该是using
,并且不需要明确的Close()
。交易有点棘手;所显示的代码目前肯定是矫枉过正的,但并未完全定义Dispose()
应该进行回滚。实际上,是在我看过的每个实现中都会发生的事情,但即使DbTransaction
(大多数提供商使用的)实际上并没有这样做,但有点令人烦恼。与TransactionScope
形成对比,明确定义没有提交的Dispose()
计为回滚。因此,我倾向使用(原谅C#):
using(var conn = GetOpenConnection())
using(var tran = conn.BeginTransaction()) {
try {
// TODO: do work
tran.Commit();
} catch {
tran.Rollback();
throw;
}
}
在复杂性方面介于两者之间。它至少没有弄乱null
- 支票。
答案 1 :(得分:13)
您所看到的是开发人员根据文档编写的代码(“Good Thing”)。基类DbTransaction(用于大多数数据提供者的事务实现)明确指出its documentation:
Dispose应该回滚事务。但是,Dispose的行为是特定于提供者的,不应该替换调用Rollback。