【问题标题】:Very Tricky ADO.Net situation that does not throw an ERROR but should非常棘手的 ADO.Net 情况,不会引发错误,但应该
【发布时间】:2026-02-06 16:40:01
【问题描述】:

我有如下 ADO.Net 代码,它调用存储过程。在存储过程中,我首先通过 SELECT 查询获取结果集,然后在 SELECT 语句后调用 RAISERROR 如果传递的 @companyId 参数值不存在。我已经多次使用 @companyId 的值对此代码运行单元测试,所以 RAISEERROR 被调用,但我从未看到对 ExecuteReader 的调用引发错误。 为什么会发生这种奇怪的违反直觉的事情?

sqlCmd = new SqlCommand("dbo.xyz_sp_Attributes_GetValues", new  SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["VHA_EDM_ConnectionString"].ConnectionString));
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("@attributeId", attributeId);
sqlCmd.Parameters.AddWithValue("@companyId", companyId);
sqlCmd.Parameters.AddWithValue("@attributeScope", "Company");
sqlCmd.Connection.Open();
SqlDataReader dr = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dr.Read())
{
    attributeValue = dr["AttributeValue"].ToString();
}

存储过程代码如下所示

SELECT col1, col2, ... where CompanyId = @companyId and AttributeId = @attributeId
if @companyId not exists (select companyId from Company where CompanyId = @companyId)
begin
 set @errMessage = N'Invalid Company Error'
 RAISERROR (@errMessage, 16, 1)
end

【问题讨论】:

    标签: sql sql-server-2008 ado.net raiserror


    【解决方案1】:

    在这种情况下,将返回多个记录集。第一个是空的,这就是为什么你没有收到任何错误。您必须调用 NextRecordset 才能得到错误。

    dr.NextResult(); // This will throw the error caused by RAISEERROR
    

    在客户端代码中进行错误检查会容易得多,而不是调用 RAISEERROR,在任何情况下都必须将其作为异常处理。

    Catch a Sql Server RAISERROR at client side using SqlDataReader

    【讨论】:

    • 我只返回一个结果集。为什么说我返回多个结果集?
    • 您没有这样做,但是 ADO.NET 返回 SP 结果的方式变成了两个记录集。你有没有遇到过这个然后使用SET NOCOUNT ON
    • 好的。我现在明白你了。感谢您非常有帮助的回复。
    最近更新 更多