我的代码:
this.sqlConn.Open();
SqlTransaction sqlT = this.sqlConn.BeginTransaction();
try {
this.updateCMD = new SqlCommand("update tblBooks set Lended=2 where BookID=@bookID", this.sqlConn);
this.insertCMD = new SqlCommand("insert tblLendLog values(@logID, @libID, @bookID, @startTime)", this.sqlConn);
this.deleteCMD = new SqlCommand("delete from tblPreConcent where LibID=@libID and BookID=@bookID", this.sqlConn);
SqlCommand insertCMD2 = new SqlCommand("insert into tblLog values(@logID, @operation, @opID, @libID, @bookID, @infos)", this.sqlConn); this.updateCMD.Transaction = sqlT;
this.insertCMD.Transaction = sqlT;
this.deleteCMD.Transaction = sqlT;
insertCMD2.Transaction = sqlT; int res = this.updateCMD.ExecuteNonQuery();
res += this.insertCMD.ExecuteNonQuery();
res += this.deleteCMD.ExecuteNonQuery();
res += insertCMD2.ExecuteNonQuery();
if(res < 4) {
sqlT.Rollback();
return "Error";
}
} catch(Exception e) {
if(this.sqlConn.State != System.Data.ConnectionState.Closed)
this.sqlConn.Close();
this.writeErrorLog("operate: LendOut, msg: " + e.Message + "Method: " + e.TargetSite.Name);
sqlT.Rollback();
return e.Message;
} finally {
sqlT.Commit();
if(this.sqlConn.State != System.Data.ConnectionState.Closed)
this.sqlConn.Close();
}
return "OK";为什么这样执行中 只要程序进入catch块或者finally块就会提示“此 SqlTransaction 已完成;它再也无法使用。”?各位大虾给看一下,这样做是哪里错了,,谢谢谢谢啦~~(ps: Sql语句中的参数部分省略了,因为不可能出现问题)

解决方案 »

  1.   

    有个明显的错误——逻辑上有问题
    因为finally里面的代码无论如何都要运行,
    如果出现异常,你就执行Rollback,
    而Rollback之后会运行finally里面的Commit()
    肯定不行
      

  2.   

    那应该怎么办呢?
    首先必须保证在执行过程中只要出现问题就要回滚,但是Commit放在try里的话,catch里的RollBack就不能工作了
    谢谢谢谢~~
      

  3.   

    但是Commit放在try里的话,catch里的RollBack就不能工作了
    ----不会呀,将sqlT.Commit();放在try模块的"}"之前就OK了
      

  4.   

    问题及改进有三处:
    1。if(this.sqlConn.State != System.Data.ConnectionState.Closed)
    this.sqlConn.Close();
    this.writeErrorLog("operate: LendOut, msg: " + e.Message + "Method: " + e.TargetSite.Name);
    sqlT.Rollback();
    ---------------
    不能先将sqlConn关闭了,然后再将sqlT回滚。
    2。sqlT.Commit();
    ---------------
    finally部分不能用commit,因为finally里的执行语句是不论有没有发生异常,而都会执行的。
    所以commit应该在try部分执行正常的时候才能执行该句的。
    3。sqlConn的关闭动作最好统一放在finally里面。因为连接总是要关闭的。修改后的代码如下:
      

  5.   

    this.sqlConn.Open();
    SqlTransaction sqlT = this.sqlConn.BeginTransaction();
    try {
    this.updateCMD = new SqlCommand("update tblBooks set Lended=2 where BookID=@bookID", this.sqlConn);
    this.insertCMD = new SqlCommand("insert tblLendLog values(@logID, @libID, @bookID, @startTime)", this.sqlConn);
    this.deleteCMD = new SqlCommand("delete from tblPreConcent where LibID=@libID and BookID=@bookID", this.sqlConn);
    SqlCommand insertCMD2 = new SqlCommand("insert into tblLog values(@logID, @operation, @opID, @libID, @bookID, @infos)", this.sqlConn); this.updateCMD.Transaction = sqlT;
    this.insertCMD.Transaction = sqlT;
    this.deleteCMD.Transaction = sqlT;
    insertCMD2.Transaction = sqlT; int res = this.updateCMD.ExecuteNonQuery();
    res += this.insertCMD.ExecuteNonQuery();
    res += this.deleteCMD.ExecuteNonQuery();
    res += insertCMD2.ExecuteNonQuery();
    if(res < 4) {
    sqlT.Rollback();
    return "Error";
    }
             else
             {
                  sqlT.Commit();
                  return "OK";
             }
    } catch(Exception e) {
    this.writeErrorLog("operate: LendOut, msg: " + e.Message + "Method: " + e.TargetSite.Name);
    sqlT.Rollback();
    return e.Message;
    } finally {
    if(this.sqlConn.State != System.Data.ConnectionState.Closed)
    this.sqlConn.Close();
    }
      

  6.   

    其中在关闭连接前,最好也要把Transaction关闭。
      

  7.   

    呀,又有回了,,也谢谢红星星的大虾~~不过,因为我的SqlConn是个全局化的东西,so,不先把它Close掉的话,writeErrorLog是会出错的~~谢谢大虾们,,让我学到了不少东西~~谢谢啦~~