C# 用于IDbConnection/IDbTransaction安全使用?

C# 用于IDbConnection/IDbTransaction安全使用?,c#,vb.net,transactions,database-connection,using-statement,C#,Vb.net,Transactions,Database Connection,Using Statement,虽然我的假设听起来似乎有些主观,但经过一些研究,我发现开发人员喜欢使用虚拟的Try/Catch而不是使用forIDbConnection/IDbTransaction处理(Close/Commit/Rollback),这种情况并不少见 即使是一些经验最丰富的开发人员和一些新开发人员也是如此。我有意不以StackOverflow或论坛链接上的任何问题为例,这样人们就不会生气。From,语句为(无意使用双关语) 有什么问题吗?考虑下面的代码: 公共子提交() Dim cn As IDbConnect

虽然我的假设听起来似乎有些主观,但经过一些研究,我发现开发人员喜欢使用虚拟的
Try/Catch
而不是使用for
IDbConnection/IDbTransaction
处理(Close/Commit/Rollback),这种情况并不少见

即使是一些经验最丰富的开发人员和一些新开发人员也是如此。我有意不以StackOverflow或论坛链接上的任何问题为例,这样人们就不会生气。From,语句为(无意使用双关语)

有什么问题吗?考虑下面的代码:

公共子提交()
Dim cn As IDbConnection={CREATE_CONNECTION}
Dim tran As IDbTransaction=无
cn.Open()
尝试
tran=cn.BeginTransaction
'在此处运行一些查询
trans.Commit()
特例
如果Not-tran什么都不是,那么tran.Rollback()
扔
最后
cn.Close()
结束尝试
端函数
假设
{CREATE_CONNECTION}
是创建连接的
子项的占位符,该子项根据数据库供应商而定,根据所有可能的最佳实践编写,不需要进一步改进

上述代码无法重写的原因是:

使用cn作为IDbConnection={CREATE_CONNECTION}
cn.Open()
将tran用作IDbTransaction=cn.BeginTransaction
'在此处运行一些查询
trans.Commit()
终端使用
终端使用

显然,第2版对它所做的事情更加直观。但也许我错过了一些重要的事情?类似于供应商特定的数据访问库实现,不在内部调用
Transaction.Commit
和/或
Connection.Close
on
Dispose
?这种方法是在不久的将来退役,还是在现代编程模式/最佳实践中不够清晰?Mono/mobileapps开发工具缺乏对
使用
关键字的调试支持


我在寻找任何支持或否定这一点的答案。最好是在原始文档中加引号的文档,例如,
在…
时不要与IDBTransation一起使用。博客链接或个人体验也可以。

我完全支持你的连接;这应该是
使用的
,不需要显式的
Close()
。交易有点棘手;目前显示的代码肯定有些过分,但是没有完全定义
Dispose()
应该执行回滚。实际上,在我所研究的每个实现中都会出现这种情况,但有一点令人不安的是,即使是
DbTransaction
(大多数提供者使用的)实际上也没有做到这一点。与
TransactionScope
相反,这里明确定义了没有提交的
Dispose()
作为回滚。因此,我倾向于使用(请原谅C#):


这在复杂性方面介于两者之间。至少,它没有在检查中混淆视听。

您看到的是开发人员根据文档编写代码(这是一件“好事”)。基类DbTransaction(用于大多数数据提供程序的事务实现)清楚地说明了:

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


这就解释了,谢谢。肯定比我的版本1更清晰。另外+1对于
GetOpenConnection
,我也倾向于将
cn.Open()
合并到一些
CreateAndOpenConnection
,因为每次调用似乎都是多余的。如果与数据库的连接关闭,事务还会回滚吗?我知道你更担心可能被锁上。谢谢。MS绝对应该在实际界面上更加清晰。
using(var conn = GetOpenConnection())
using(var tran = conn.BeginTransaction()) {
    try {
        // TODO: do work
        tran.Commit();
    } catch {
        tran.Rollback();
        throw;
    }
}