如何在RollBack上捕获异常 [英] How to catch exception on RollBack

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

问题描述

对于已经存在于catch子句中的SqlTransaction RollBack,实现错误处理的最佳方法是什么?我的代码大致如下:

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

使用(SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()){
try {
// code
//更多代码
//和更多的代码
}
catch(Exception ex){
//如果RollBack()有异常,会怎么样?
objSqlTrans.Rollback();
throw ex;
}
}
}

我相信我的应用程序try块中有一个例外,而这个异常又被捕获在catch块中,然后尝试了RollBack。但是,我看到的错误说明了一些关于SqlTransaction.ZombieCheck()的问题,这使我想知道RollBack()本身是否也引发了异常。那么,我需要在RollBack()中实现一些类型的错误处理?首先如何处理catch块中的执行异常?



编辑 - 我的所有代码:

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

objSqlConn 。打开();

//开始事务
使用(SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()){

try {
//在db中创建文件根据
// ... FileStream指向的位置,在磁盘上创建它)
SqlCommand objSqlCmd = new SqlCommand(usp_FileAdd,objSqlConn,objSqlTrans);
objSqlCmd.CommandType = CommandType.StoredProcedure;

// Sql参数 - 报告名称
SqlParameter objSqlParam1 =新的SqlParameter(@ ObjectID,SqlDbType.Int);
objSqlParam1.Value = objID;

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

//将Sql参数添加到命令obj
objSqlCmd.Parameters.Add(objSqlParam1);
objSqlCmd.Parameters.Add(objSqlParamOutput);

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

// FileStream的路径
string path = objSqlCmd.Parameters [@ filepath]。Value.ToString();

//重置命令对象以获取FileStream
objSqlCmd = new SqlCommand(
SELECT GET_FILESTREAM_TRANSACTION_CONTEXT(),
objSqlConn,
objSqlTrans);

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

if(obj!= DBNull.Value){
//表示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 =新字节[4096];
int read;

fs.Seek(0,SeekOrigin.Begin);

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

sqlFS.Close();
}

//提交事务
objSqlTrans.Commit();
}
catch(Exception ex){
objSqlTrans.Rollback();
throw ex;
}
}
}


解决方案

你已经有了

  using(SqlTransaction objSqlTrans = objSqlConn.BeginTransaction())

当使用块没有被提交时,这将导致事务被回滚。



所以我将完全删除catch块。对于在回滚失败时会发生什么,我将首先认识到这是一个非常糟糕的情况,并遵循Eric Lippert对类似问题的建议。 这里


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

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

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