我试图为这个问题找到一个有用的答案,但失败了(我发现最近的答案是这)。我有一个C#应用程序调用一个存储过程,它使用SQL TRY/CATCH来处理错误。我可以用这样的样例存储过程来复制这个问题:
if object_id('dbo.TestSQLError') is not null drop proc dbo.TestSQLError
go
create proc dbo.TestSQLError
as
begin try
select 1 / 0
end try
begin catch
raiserror('Bad tings appen mon', 16, 1)
end catch然后一个像这样的小程序:
namespace TestSQLError
{
class Program
{
public const string CONNECTION_STRING = @"data source=localhost\koala; initial catalog=test; integrated security=true;";
static void Main(string[] args)
{
try
{
using (SqlConnection conn = new SqlConnection(CONNECTION_STRING))
{
SqlCommand cmd = new SqlCommand("dbo.TestSQLError", conn) { CommandType = System.Data.CommandType.StoredProcedure };
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine(rdr.GetValue(0).ToString());
}
rdr.Close();
}
conn.Close();
}
Console.WriteLine("Everything looks good...");
}
catch (SqlException se)
{
Console.WriteLine("SQL Error: " + se.Message);
throw se;
}
catch (Exception e)
{
Console.WriteLine("Normal Error: " + e.Message);
throw e;
}
Console.ReadLine();
}
}
}存储过程会引发一个级别为16的错误,据我所知,这个错误应该足够值得错误使用。然而,控件从不跳转到catch块;它只是像没有出错一样缓慢地通过。
我读到有人建议使用OUTPUT参数..。这是我可以做的,但似乎我错过了一些基本的、简单的东西。有人能帮忙吗?
更新:--如果我使用ExecuteNonQuery(),错误就会传播得很好。但是,我的用例是一个执行DML并基于该DML返回数据的过程。也许答案是“不要那样做”,但最好知道是否有一种方法可以在获取结果时简单地捕捉错误。
发布于 2017-07-24 22:13:45
原因是因为引发错误是在数据读取器中的第一个结果集结束之后,并且只有在数据读取器上调用NextResult()时才会得到错误!
当使用SqlDataReader时,它只会迭代第一个结果集,在本例中,这将是存储过程中的选择。
试着查看更多细节这里
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (!rdr.IsClosed())
{
while (rdr.Read())
{
Console.WriteLine(rdr.GetValue(0).ToString());
}
if (!rdr.NextResult())
{
rdr.Close();
}
}
}发布于 2017-07-24 22:11:40
我可以提出三项建议:
CommandType.Text而不是CommandType.StoredProcedure。现在可能已经修复了这个问题,但几年前,我发现CommandType.StoredProcedure总是将消息输出缓冲为大约50次,而CommandType.Text则允许消息立即返回到C#。WITH NOWAIT提示添加到RAISERROR代码中。FireInfoMessageEventOnUserErrors属性。您确实希望处理InfoMessage事件。我不确定这些能解决你的问题,但它们应该给你一些方向。
https://stackoverflow.com/questions/45290672
复制相似问题