SqlTransaction导致应用程序崩溃时出错?

时间:2011-12-16 14:50:00

标签: c# asp.net visual-studio-2008-sp1 sqltransaction

以下是一些背景知识:我们的网站会定期崩溃,无法重新启动IIS;这几乎总是在修补DLL的一小时内发生(我们使用网站项目,而不是Web应用程序项目,因此每个ASPX页面都是一个单独的DLL)。

在进行一些研究时,我发现我们的自制DAL可以在调试时导致内置的Web服务器与Visual Studio实际停止工作并在存储过程中遇到SQL错误时关闭(我的意思是不仅会抛出浏览器中显示的异常,而且实际上会说Web服务器出现错误并需要关闭!)

在进一步挖掘时,错误似乎与DAL中所有事务(包括Select语句)的事务使用有关。似乎发生了这样的事情:

  1. 尝试执行存储过程,存储过程因列丢失/无效或其他错误而失败。
  2. 应用程序代码捕获错误并重新抛出它(糟糕,是的,但我没有写这个)。
  3. 尽管异常,事务尝试提交,但在NullReferenceException行上获得transaction.Commit()(似乎在Connection属性上,因为存在事务对象)。此NullRef似乎无法捕获(我尝试了一个强制崩溃与无效Sproc并且NullRef从未被捕获的演示,即使输出错误的类型为System.NullReferenceException
  4. 交易抛出错误,表示“交易已完成且不再可用”。
  5. ???但VS Web服务器崩溃了。调试此部分似乎挂在上面的异常上,永远不会离开该方法。
  6. 现在,我不知道这是否是导致IIS崩溃的原因,但它似乎很可疑,并且在任何情况下都是一个明显的错误。

    之前没有处理过交易并且只有它们的基本概念,我的第一个问题是为什么事务在抛出异常后仍然试图提交?我的第二个问题是如何修复失败的提交以及可能无限循环的异常,直到服务器死亡。添加这样的东西是不是有意义(该方法采用名为transaction的SqlTransaction参数):

    catch (SqlException se) 
    {
        if (transaction != null)
        {
            transaction.Rollback();
        }
        throw;
    }
    

    这个小小的改动是否会修复我认为崩溃IIS的常量异常循环? DAL本身非常脆弱,具体使用在数百个文件中,所以我无法正确地重写它。

    编辑整个代码块就是这样(遗留代码 - 使用旧的Microsoft数据访问块帮助程序):

        public static DataSet ExecuteDatasetStoredProc(SqlConnection conn, String storedProcName, SqlTransaction transaction, params SqlParameter[] storedProcParms)
        {
            try
            {
                // Execute the stored proc
                if (transaction != null)
                {
                    return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, storedProcName, storedProcParms);
                }
                else
                {
                    return SqlHelper.ExecuteDataset(conn, CommandType.StoredProcedure, storedProcName, storedProcParms);
                }
            }
            catch (SqlException se)
            {
                throw new ApplicationException("Error calling " + storedProcName + ". " + se.Message, se);
            }
        }
    

    但是,如果catch块执行,那么事务仍然会尝试提交,这似乎导致了挂起。

1 个答案:

答案 0 :(得分:0)

如果您将交易代码包装在try catch

中,也可以更改
Try
{
// your code that you assign and execute the SQl

}
catch (SQLException sqlex)
{
  try 
  {
    //try to do the rollback here.. don't always assume the commit or rollback will work
  }
  catch (Your SQL Exception ex)
  {
  }
}