【问题标题】:Using for IDbConnection/IDbTransaction safe to use?使用 IDbConnection/IDbTransaction 安全吗?
【发布时间】:2013-05-29 23:46:22
【问题描述】:

虽然我的假设似乎听起来很主观,但经过一些研究,我发现找到喜欢虚拟 Try/Catch 而不是使用 Using statement 进行 IDbConnection/IDbTransaction 处理的开发人员并不少见(关闭/提交/回滚)。

即使是一些经验最丰富的开发人员和一些新开发人员也是如此。我故意不以 StackOverflow 或论坛链接上的任何问题为例,这样人们就不会生气。从what I foundUsing 声明是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 ...。博客链接或个人经历也可以。

【问题讨论】:

    标签: c# vb.net transactions database-connection using-statement


    【解决方案1】:

    我完全支持你的连接;那应该是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-checks 搞混。

    【讨论】:

    • 这就解释了,谢谢。绝对比我的版本 #1 更清晰。还为GetOpenConnection +1,我也倾向于将cn.Open() 合并到一些CreateAndOpenConnection 中,因为每次都打电话似乎是多余的。
    • 如果与数据库的连接关闭,事务还会回滚吗?我了解您更担心可能会被锁定。
    【解决方案2】:

    您看到的是开发人员根据文档进行编码(“好事”)。基类 DbTransaction(用于大多数数据提供者的事务实现)在 its documentation 中明确声明:

    Dispose 应该回滚事务。但是,Dispose 的行为是特定于提供者的,不应替代调用 Rollback。

    【讨论】:

    • 谢谢。 MS 肯定应该在实际界面上让它更清晰。
    猜你喜欢
    • 2012-04-08
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 2011-01-05
    • 2012-03-31
    • 2013-01-23
    相关资源
    最近更新 更多