如何赶上回滚异常 [英] How to catch exception on RollBack

查看:157
本文介绍了如何赶上回滚异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是实现错误处理,已经在catch子句存在的SqlTransaction回滚的最佳方法是什么?我的code大致是这样的:

 使用(SqlConnection的objSqlConn =新的SqlConnection(connStr)){
  objSqlConn.Open();

  使用(的SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()){
    尝试 {
      // code
      //更多code
      //多code
    }
    赶上(例外前){
      //如果回滚()有异常,会发生什么?
      objSqlTrans.Rollback();
      抛出前;
    }
  }
}
 

我相信我的应用程序必须在try块,这又被夹在catch块,然后回滚尝试异常。但是,我看到的错误说了一些关于SqlTransaction.ZombieCheck(),它是让我知道如果回滚()本身抛出异常也是如此。所以,我需要实现某种类型的错误处理在回滚()?我该怎么做了,并设法保住这将执行到catch块摆在首位?

异常

编辑 - 我所有的code:

 使用(SqlConnection的objSqlConn =新的SqlConnection(connStr)){

    objSqlConn.Open();

    //开始交易
    使用(的SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()){

        尝试 {
            //创建的数据库文件(这反过来又在磁盘上创建它根据购买本
            // ...的FileStream分)
            SqlCommand的objSqlCmd =新的SqlCommand(usp_FileAdd,objSqlConn,objSqlTrans);
            objSqlCmd.CommandType = CommandType.StoredProcedure;

            // SQL参数 - 报告名称
            的SqlParameter objSqlParam1 =新的SqlParameter(@对象ID,SqlDbType.Int);
            objSqlParam1.Value = OBJID;

            //的Sql OUT参数 - 返回文件路径
            的SqlParameter objSqlParamOutput =新的SqlParameter(@文件路径,SqlDbType.VarChar,-1);
            objSqlParamOutput.Direction = ParameterDirection.Output;

            //添加SQL参数指挥OBJ
            objSqlCmd.Parameters.Add(objSqlParam1);
            objSqlCmd.Parameters.Add(objSqlParamOutput);

            //执行命令对象
            objSqlCmd.ExecuteNonQuery();

            //路径到FileStream
            字符串路径= objSqlCmd.Parameters [@文件路径] Value.ToString()。

            //复位命令对象获取的FileStream
            objSqlCmd =新的SqlCommand(
                SELECT GET_FILESTREAM_TRANSACTION_CONTEXT(),
                objSqlConn,
                objSqlTrans);

            //执行命令对象
            obj对象= objSqlCmd.ExecuteScalar();

            如果(OBJ!=的DBNull.Value){
                //字节数组再presenting因此FileStream
                byte []的fsBytes =(byte []的)目标文件;

                SqlFileStream sqlFS =新SqlFileStream(路径,fsBytes,FileAccess.Write);

                使用(的FileStream FS = fi.OpenRead()){
                    // byte []的B =新的字节[1024];
                    byte []的B =新的字节[4096];
                    INT读取;

                    fs.Seek(0,SeekOrigin.Begin);

                    而((读= fs.Read(B,0,b.length个))大于0){
                        sqlFS.Write(B,0,读);
                    }
                }

                sqlFS.Close();
            }

            //提交事务
            objSqlTrans.Commit();
        }
        赶上(例外前){
            objSqlTrans.Rollback();
            抛出前;
        }
    }
}
 

解决方案

您已经有了

 使用(的SqlTransaction objSqlTrans = objSqlConn.BeginTransaction())
 

这将导致事务被回滚,如果它没有被COMMITED时使用块的结束。

所以,我将完全删除catch块。

至于什么时候回滚失败我会承认这是一个非常糟糕的情况是在并按照埃里克利珀的建议类似的问题开始会发生什么。 <一href="http://blogs.msdn.com/ericlippert/archive/2010/02/25/careful-with-that-axe-part-two-what-about-exceptions.aspx"相对=nofollow>这里

What is the best way to implement error handling for a SqlTransaction RollBack that already exists within a catch clause? My code is roughly like this:

using (SqlConnection objSqlConn = new SqlConnection(connStr)) {
  objSqlConn.Open();

  using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()) {
    try {
      // code
      // more code
      // and more code
    }
    catch (Exception ex) {
      // What happens if RollBack() has an exception?
      objSqlTrans.Rollback();
      throw ex;
    }
  }
}

I believe that my application had an exception in the try block, which in turn was caught in the catch block and then the RollBack was attempted. However, the error that I'm seeing says something about a SqlTransaction.ZombieCheck(), which is making me wonder if the RollBack() itself threw an exception as well. So, do I need to implement some type of error handling at the RollBack()? How do I do that and manage to hold on to the exception that put the execution into the catch block in the first place?

EDIT - All of my code:

using (SqlConnection objSqlConn = new SqlConnection(connStr)) {

    objSqlConn.Open();

    // Begin Transaction
    using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()) {

        try {
            // Create file in db (which in turn creates it on disk according to where the 
            // ...FileStream points)
            SqlCommand objSqlCmd = new SqlCommand("usp_FileAdd", objSqlConn, objSqlTrans);
            objSqlCmd.CommandType = CommandType.StoredProcedure;

            // Sql parameter - report name
            SqlParameter objSqlParam1 = new SqlParameter("@ObjectID", SqlDbType.Int);
            objSqlParam1.Value = objID;

            // Sql out parameter - returns the file path
            SqlParameter objSqlParamOutput = new SqlParameter("@filepath", SqlDbType.VarChar, -1);
            objSqlParamOutput.Direction = ParameterDirection.Output;

            // Add Sql parameters to command obj
            objSqlCmd.Parameters.Add(objSqlParam1);
            objSqlCmd.Parameters.Add(objSqlParamOutput);

            // Execute command object
            objSqlCmd.ExecuteNonQuery();

            // Path to the FileStream
            string path = objSqlCmd.Parameters["@filepath"].Value.ToString();

            // Reset command object to get FileStream
            objSqlCmd = new SqlCommand(
                "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()",
                objSqlConn,
                objSqlTrans);

            // Execute command object
            Object obj = objSqlCmd.ExecuteScalar();

            if (obj != DBNull.Value) {
                // Byte array representing the FileStream
                byte[] fsBytes = (byte[])obj;

                SqlFileStream sqlFS = new SqlFileStream(path, fsBytes, FileAccess.Write);

                using (FileStream fs = fi.OpenRead()) {
                    //byte[] b = new byte[1024];
                    byte[] b = new byte[4096];
                    int read;

                    fs.Seek(0, SeekOrigin.Begin);

                    while ((read = fs.Read(b, 0, b.Length)) > 0) {
                        sqlFS.Write(b, 0, read);
                    }
                }

                sqlFS.Close();
            }

            // Commit the transaction
            objSqlTrans.Commit();
        }
        catch (Exception ex) {
            objSqlTrans.Rollback();
            throw ex;
        }
    }
}

解决方案

You've already got

using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction())

This will cause the Transaction to be rolled back when it the using block ends if it hasn't been commited.

So I would remove the catch block entirely.

As for what happens when the rollback fails I would start by recognizing this as a very bad situation to be in and follow Eric Lippert's advice on a similar problem. here

这篇关于如何赶上回滚异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆