使用BeginTransaction和Dapper.IDbConnection的正确方法

Kri*_*ana 25 .net c# orm idbconnection dapper

这是使用的正确方法是BeginTransaction()IDbConnection在小巧玲珑的?

我创建了一个必须使用的方法BeginTransaction().这是代码.

using (IDbConnection cn = DBConnection)
{
    var oTransaction = cn.BeginTransaction();

    try
    {
        // SAVE BASIC CONSULT DETAIL
        var oPara = new DynamicParameters();
        oPara.Add("@PatientID", iPatientID, dbType: DbType.Int32);
        ..........blah......blah............
    }
    catch (Exception ex)
    {
        oTransaction.Rollback();
        return new SaveResponse { Success = false, ResponseString = ex.Message };
    }
}
Run Code Online (Sandbox Code Playgroud)

当我执行上面的方法 - 我有一个例外 -

操作无效.连接已关闭.

这是因为在打开连接之前无法开始事务.所以当我添加这一行:时cn.Open();,错误得到解决.但我已经读过某个地方,手动打开连接是不好的做法!! Dapper仅在需要时才打开连接.

在Entity框架中,您可以使用a处理事务TransactionScope.

所以我的问题是cn.Open()...在没有在Dapper中添加行来处理事务的好习惯是什么?我想应该有一些正确的方法.

Mar*_*ell 54

手动打开连接不是"不好的做法"; dapper使用开放或封闭连接作为方便,仅此而已.一个常见的问题是,人们有连接被打开,未使用,连接太久而没有将它们释放到池中 - 但是,在大多数情况下这不是问题,你当然可以这样做:

using(var cn = CreateConnection()) {
    cn.Open();
    using(var tran = cn.BeginTransaction()) {
        try {
            // multiple operations involving cn and tran here

            tran.Commit();
        } catch {
            tran.Rollback();
            throw;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,dapper有一个可选参数来传递事务,例如:

cn.Execute(sql, args, transaction: tran);
Run Code Online (Sandbox Code Playgroud)

我实际上试图IDbTransaction该工作上进行类似的扩展方法,因为事务总是暴露.Connection ; 这将允许:

tran.Execute(sql, args);
Run Code Online (Sandbox Code Playgroud)

但这在今天不存在.

TransactionScope是另一种选择,但有不同的语义:这可能涉及LTM或DTC,主要取决于......好吧,运气.创建一个包装器也很诱人,IDbTransaction不需要try/ catch- 更像是如何TransactionScope工作; 类似的东西(这也不存在):

using(var cn = CreateConnection())
using(var tran = cn.SimpleTransaction())
{
    tran.Execute(...);
    tran.Execute(...);

    tran.Complete();
}
Run Code Online (Sandbox Code Playgroud)

  • @ marc-gravell - 在回滚的情况下,你是否必须显式调用`tran.RollBack`?处理时未自动回滚的交易? (3认同)

Fel*_*ano 6

你不应该打电话

cn.Close();
Run Code Online (Sandbox Code Playgroud)

因为使用块也会尝试关闭.对于事务部分,是的,您也可以使用TransactionScope,因为它不是与实体框架相关的技术.看看这个SO答案:https://stackoverflow.com/a/6874617/566608 它解释了如何在事务范围内登记您的连接.重要的方面是:连接自动登记在事务IIF中,您打开范围内的连接.