我在.Net 4.0.30319 SP1Rel中的SqlClient存在问题,当我的存储过程处理以下错误时,不会抛出异常:
子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。
我已经创建了一个小程序和存储过程来演示这个。 Sql Server版本是9.0.4053。
create proc test
as
select case (select 1 union select 2) when 1 then 1 else 2 end
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection("<your connection string>");
conn.Open();
SqlCommand cmd = new SqlCommand("test", conn);
cmd.CommandType = CommandType.StoredProcedure;
try
{
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
Console.WriteLine("Finished");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
}
}
运行此应用程序只需将“完成”写入控制台。
在de SQL Server Management Studio中运行存储过程'test'将在结果窗格中报告错误,如:
Msg 512,Level 16,State 1,Procedure test,Line 3 子查询返回的值超过1。当子查询遵循=,!=,&lt;,&lt; =,&gt;,&gt; =或子查询用作表达式时,不允许这样做。
通过以下示例替换存储过程将给出预期的System.Data.SqlClient.SqlException。
alter proc test
as
raiserror('Not good at all!', 16, 1)
我发现的其他一些定义也不会抛出异常。
alter proc test
as
select case (select 1 union select 2) when 1 then 1 else 2 end
raiserror('Not good at all!', 16, 1)
这表明select语句会停止执行存储过程。
alter proc test
as
select 1/0
我的结论是SqlClient无法正确识别tSql批处理的错误状态。有没有人遇到这个并找到了解决方案?我总是信任.Net框架,在任何tSql错误上抛出异常。
答案 0 :(得分:2)
感谢Martin的有用和迅速的评论,我找到了这种奇怪行为的原因。
过去,其中一位程序员在阅读器中读取读取内容以查看是否有任何行,如下所示:
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.HasRows)
{
while (reader.Read()) { /* Do Something */ }
}
我不知道为什么,因为当没有行时,read()方法会在第一次调用时返回false。
无论如何,当tSQL中发生错误时,HasRows属性返回false并且从未调用过Read()方法。由于这个原因,SQL错误没有透露给SqlClient而且没有异常被抛出。
您可以将此代码段添加到示例项目中,就在ExecuteReader之后,有或没有HasRows测试,并查看效果。