You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Entity Framework Core无法捕获存储过程SQL catch块抛出的异常

问题原因

当存储过程在TRY/CATCH块的CATCH部分抛出错误时,SQL Server的消息发送逻辑导致EF Core无法捕获错误:

  • TRY块中的报错触发CATCH后,没有结果集被生成返回
  • SQL Server会先向客户端发送「结果集结束」的信号,之后才传递错误信息
  • EF Core的FromSqlInterpolated配合ToList()在收到「结果集结束」信号后,就终止了数据读取流程,不会再处理后续的错误消息

而移除TRY/CATCH直接抛出错误时,SQL Server会立即发送错误信息,EF Core能正常捕获。

解决方案

由于你需要保留TRY/CATCH执行额外操作,可采用以下两种方案:

方案1:改用ExecuteSqlInterpolated执行存储过程

如果存储过程无需返回实体结果集,用ExecuteSqlInterpolated替代FromSqlInterpolated,它会完整读取SQL Server返回的所有消息,包括后续的错误:

using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using SQLExceptionTest.Models;

var builder = new DbContextOptionsBuilder<TESTNU40Context>();
builder.UseSqlServer("Data Source=MyServer; Initial Catalog=MyDB; Integrated Security=True; TrustServerCertificate=True");

var context = new TESTNU40Context(builder.Options);

try
{
    var affectedRows = context.Database.ExecuteSqlInterpolated($"SqlExceptionTest");
    Console.WriteLine($"Affected rows: {affectedRows}");
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
}

Console.ReadLine();

方案2:在CATCH块中先返回错误标记结果集

修改存储过程,在抛出错误前先返回一个包含错误标识的结果集,这样EF Core在读取结果集后会继续处理后续的错误:

create procedure SqlExceptionTest
as
    set nocount on;

    begin try
        select 1/0 as test;
    end try
    begin catch
        -- 返回错误标记结果集
        SELECT 'Error' AS ResultType, ERROR_MESSAGE() AS ErrorMessage;
        -- 抛出错误
        throw 51000, 'throw in catch', 1;
    end catch

对应的代码可以先检查结果集的错误标识,同时EF Core会捕获后续抛出的错误:

using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using SQLExceptionTest.Models;

var builder = new DbContextOptionsBuilder<TESTNU40Context>();
builder.UseSqlServer("Data Source=MyServer; Initial Catalog=MyDB; Integrated Security=True; TrustServerCertificate=True");

var context = new TESTNU40Context(builder.Options);

try
{
    var r = context.SQLExceptionTestResults.FromSqlInterpolated($"SqlExceptionTest").ToList();
    // 检查结果集中的错误标记
    if(r.Any(item => item.ResultType == "Error"))
    {
        Console.WriteLine($"Business error: {r.First().ErrorMessage}");
    }
    Console.WriteLine($"Result count: { r.Count}");
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
}

Console.ReadLine();

补充提示

  • 确保使用较新版本的EF Core和Microsoft.Data.SqlClient,旧版本可能存在类似的消息处理缺陷
  • 若无需返回实体结果,方案1更简洁;若需同时返回结果和处理错误,方案2更适配业务场景

内容的提问来源于stack exchange,提问作者bowend01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:34:59