用于IDbConnection/IDbTransaction安全使用?

Neo*_*isk 9 c# vb.net database-connection transactions using-statement

虽然我的假设似乎听起来很主观,但经过一些研究后,我发现找到喜欢虚拟对象的开发人员Try/Catch而不是使用Using语句进行IDbConnection/IDbTransaction处理(Close/Commit/Rollback)并不罕见.

即使是一些经验最丰富的开发人员和一些新开发人员也是如此.我故意不会在StackOverflow或论坛链接上引用任何问题作为示例,因此人们不会被冒犯.根据我的发现,使用声明是安全的(没有双关语).

它有什么问题吗?请考虑以下代码:

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
Run Code Online (Sandbox Code Playgroud)

假设{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
Run Code Online (Sandbox Code Playgroud)

很明显,版本#2对它正在做的事情更直观.但也许我错过了一些重要的东西?事情是这样的数据访问库的供应商特定的实现,不调用Transaction.Commit和/或Connection.CloseDispose内部?这种方法是在不久的将来退役,还是在现代编程模式/最佳实践中不够明确?单声道/移动应用程序开发工具缺乏对Using关键字的调试支持?

我正在寻找任何支持或否认这一点的答案.最好是带有原始文档引用的那个,类似于Do not use Using with IDbTransaction when ....博客或个人经验的链接也可以.

Mar*_*ell 18

我完全和你在一起; 应该是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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在复杂性方面,它介于两者之间.null至少,它并没有搞乱 - 检查.


Mic*_*ter 13

您所看到的是开发人员根据文档编写的代码("好事").基类DbTransaction(用于大多数数据提供者的事务实现)在其文档中明确说明:

Dispose应该回滚事务.但是,Dispose的行为是特定于提供程序的,不应替换调用Rollback.