首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在RollBack上捕获异常

如何在RollBack上捕获异常
EN

Stack Overflow用户
提问于 2010-04-05 16:28:14
回答 2查看 1.3K关注 0票数 2

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

代码语言:javascript
复制
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;
    }
  }
}

我认为我的应用程序在try块中有一个异常,然后在catch块中捕获该异常,然后尝试RollBack。但是,我看到的错误说明了一个SqlTransaction.ZombieCheck(),这让我怀疑RollBack()本身是否也抛出了异常。那么,我是否需要在RollBack()中实现某种类型的错误处理?我如何做到这一点,并设法保持异常,即将执行放在catch块的首要位置?

编辑-我所有的代码:

代码语言:javascript
复制
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;
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-04-05 17:03:30

你已经有了

代码语言:javascript
复制
using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction())

这将导致当使用块结束时事务被回滚,如果它还没有被执行。

所以我会把catch块完全移除。

至于当回滚失败时会发生什么,我首先要认识到这是一个非常糟糕的情况,并遵循Eric关于类似问题的建议。这里

票数 1
EN

Stack Overflow用户

发布于 2010-04-05 16:35:58

这个片段应该是这样的:

代码语言:javascript
复制
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?
     try {
        objSqlTrans.Rollback();
     } catch (Exception ex2) {
        /* can't roll back -- db gone? db will do it for us since we didn't commit. */
     }
     throw;
   }
 }
}

编辑:想想看,在这个特定的情况下,完全不需要尝试/捕捉,因为使用未提交的事务关闭连接会回滚事务,因此块可以如下所示:

代码语言:javascript
复制
using (SqlConnection objSqlConn = new SqlConnection(connStr)) {
 objSqlConn.Open();

 using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()) {
  // code
  // more code
  // and more code
 }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2579515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档