sql – 更好的做法是明确地调用事务回滚或让异常触发隐式回滚?

前端之家收集整理的这篇文章主要介绍了sql – 更好的做法是明确地调用事务回滚或让异常触发隐式回滚?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在下面的代码中,如果在执行sql语句时抛出任何异常,我们应该期待事务的隐式回滚,因为事务没有提交,它超出了范围,它被处理:
using (DbTransaction tran = conn.BeginTransaction())
{
    //
    // Execute sql statements here...
    //
    tran.Commit();
}

以上是可接受的做法,或者应该捕获异常并明确地调用tran.Rollback(),如下所示:

using (DbTransaction tran = conn.BeginTransaction())
{
    try
    {
        //
        // Execute sql statements here...
        //
        tran.Commit();
    }
    catch
    {
        tran.Rollback();
        throw;
    }
}

解决方法

前任的.如果您查找类似主题的MSND样本,例如 TransactionScope,他们都赞成隐式回滚.有各种各样的原因,但我会给你一个非常简单的一个:当你捕获异常时,事务可能已经回滚了.许多错误回滚挂起的事务,然后将控制权返回给客户端,ADO.Net在事务已经在服务器上回滚之后引发了CLR sqlException(1205 DEADLOCK是这种错误的典型示例),因此显式Rollback()调用最多只是一个no-op,更糟糕的是一个错误. DbTransaction的提供者(例如sqlTransaction)应该知道如何处理这种情况,例如.因为服务器和客户端之间有明确的聊天,通知事务已经回滚,Dispose()方法做正确的事情.

第二个原因是事务可以嵌套,但是ROLLBACK的语义是一个回滚可以回滚所有事务,所以你只需要调用它一次(不同于Commit(),它只提交内部最多的事务,并且必须被配对每个开始).再次,Dispose()做正确的事情.

更新

SqlConnection.BeginTransaction()的MSDN示例实际上有利于第二种形式,并在catch块中显式显示Rollback().我怀疑技术作者只是想在一个单一的样本中显示Rollback()和Commit(),注意到他需要如何在Rollback周围添加一个第二个try / catch块,以规避我最初提到的一些问题.

猜你在找的MsSQL相关文章