2

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

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

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

  1. 尝试执行存储过程,存储过程由于缺少/无效列或其他错误而失败。
  2. 应用程序代码捕获错误并重新抛出它(不好,是的,但我没有写这个)。
  3. 尽管有异常,事务仍试图提交,得到一个NullReferenceExceptiontransaction.Commit()行了(似乎在Connection属性上,因为有一个事务对象)。此外,这个 NullRef 似乎无法被捕获(我尝试了一个演示,该演示因无效的 Sproc 而强制崩溃,并且 NullRef 从未被捕获,即使输出错误将其类型为System.NullReferenceException
  4. 事务引发错误,例如“事务已完成且不再可用”。
  5. ???但是 VS Web 服务器崩溃了。调试这部分似乎挂在上面的异常上,永远不会离开方法。

现在,我不知道这是否是导致 IIS 崩溃的原因,但它似乎很可疑,无论如何这都是一个明显的错误。

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

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

这个小改动会修复我认为导致 IIS 崩溃的持续异常循环吗?DAL 本身非常脆弱,具体用于数百个文件,因此我无法正确地从头开始重写它。

编辑整个代码块是这样的(同样,遗留代码 - 使用旧的微软数据访问块助手):

    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 块执行事务仍会尝试提交,这似乎会导致挂起。

4

1 回答 1

-1

如果您将事务代码包装在 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)
  {
  }
}
于 2011-12-16T14:55:46.247 回答