【发布时间】:2011-12-16 14:49:59
【问题描述】:
这里有一些背景:我们的网站会定期崩溃到不得不重新启动 IIS 的程度;这几乎总是在修补 DLL 的一个小时内发生(我们使用的是网站项目,而不是 Web 应用程序项目,因此每个 ASPX 页面都是一个单独的 DLL)。
在进行一些研究时,我发现我们的自制 DAL 在调试时会导致带有 Visual Studio 的内置网络服务器在存储过程中遇到 SQL 错误时实际停止工作并关闭(我的意思是不仅会抛出一个显示在浏览器中的异常,它实际上会说Web服务器遇到错误需要关闭!)
在进一步挖掘中,该错误似乎与 DAL 中所有内容(包括 Select 语句)的事务使用有关。似乎发生的事情是这样的:
- 尝试执行存储过程,存储过程由于缺少/无效列或其他错误而失败。
- 应用程序代码捕获错误并重新抛出它(不好,是的,但我没有写这个)。
- 尽管出现异常,事务仍尝试提交,在
transaction.Commit()行上获得NullReferenceException(似乎在Connection属性上,因为存在事务对象)。此外,这个 NullRef 似乎无法被捕获(我尝试了一个演示,该演示使用无效的 Sproc 强制崩溃并且 NullRef 从未被捕获,即使输出错误的类型为System.NullReferenceException) - 事务引发错误,类似于“事务已完成且不再可用”。
- ???但是 VS Web 服务器崩溃了。调试这部分似乎挂在上面的异常上,永远不会离开方法。
现在,我不知道这是否是导致 IIS 崩溃的原因,但它似乎很可疑,无论如何这是一个明显的错误。
之前没有处理过事务并且只有它们的基本概念,我的第一个问题是为什么在抛出异常后事务仍在尝试提交?我的第二个问题是如何修复失败的提交和可能的无限循环异常,直到服务器死机。添加这样的东西不是很有意义吗(该方法需要一个名为transaction的SqlTransaction参数):
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 块执行,事务仍然会尝试提交,这似乎会导致挂起。
【问题讨论】:
-
对于初学者来说,发布您拥有事务代码的整个代码块。空引用意味着您没有创建事务的实例。例如 SQLTransaction trans;那么您必须将该事务分配给 SqlCommand 对象 sqlComm.Transaction = trans 类似的东西..根据上面“缺少列”中的错误描述检查存储过程并确保您的 Select 语句、更新、删除 .. 是收到确切的参数,希望你没有这样做,当你只需要几个字段而不是很多时选择 *'s .. 需要查看代码和查询
标签: c# asp.net visual-studio-2008-sp1 sqltransaction