首页 > 解决方案 > SqlDataReader 和 T-SQL:在使用来自 C# 的“异步”调用时使用“try...catch”和“throw”时不会传播异常

问题描述

我从这样的命令中得到一个数据读取器:

reader = command.ExecuteReaderAsync()

MRE 命令文本:

begin try
    exec('select * from (SELECT 1 as ID) as nnn where ID = ''sdfsdf''') 
end try 
begin catch 
    throw;
end catch

此命令会导致 SQL 出错:

将 varchar 值“sdfsdf”转换为数据类型 int 时转换失败

但是如果我使用reader.Read()它,它不会返回没有错误的结果。在没有任何信息的情况下使事务回滚。

如何获取有关执行阅读器期间发生的错误的信息?

标签: c#sql-servertsqlasynchronousado.net

解决方案


为了进入您的 TSQL CATCH 块,在您捕获异常exec之前,执行完成并向客户端发送一个零行结果集和一个“行计数” 。THROW

打开就可以看到改变的顺序

con.FireInfoMessageEventOnUserErrors = true;
con.InfoMessage += (s, a) => Console.WriteLine($"Message: {a.Message}");

如果你跑

exec('select * from (SELECT 1 as ID) as nnn where ID = ''sdfsdf''') 

在调用 SqlCommand.ExecuteReader() 返回之前,您将看到错误消息。但是使用 CATCH 和 THROW SqlCommand.ExecuteReader() 在收到错误消息之前返回。

您可以像这样捕获错误:

using (var rdr = cmd.ExecuteReader())
{
    do
    {
        while (rdr.Read())
        {
            //. . .
        }
    }
    while (rdr.NextResult());  //this will throw the SqlException
}

推荐阅读