EF中调用存储过程时,如何捕获含ERROR_SEVERITY()的SQL错误?
解决Entity Framework调用存储过程捕获自定义错误信息的问题
这个问题我之前也碰到过,其实核心在于EF的ExecuteSqlRawAsync和FromSqlRaw的定位不同,咱们一步步来解决你的疑问:
为什么ExecuteSqlRawAsync拿不到错误返回值?
ExecuteSqlRawAsync是专门用于执行非查询操作(比如Insert/Update/Delete)的方法,它只会返回受影响的行数,不会处理存储过程中通过SELECT返回的结果集——这就是你拿不到ERROR_SEVERITY()返回值的原因。
方案1:用FromSqlRaw获取存储过程返回的错误结果
如果你的存储过程是通过SELECT返回错误信息(像你现在的写法),那确实需要用FromSqlRaw来捕获这个结果集,步骤如下:
- 首先定义一个和存储过程返回字段匹配的实体类:
public class StoredProcedureError { public int ErrorSeverity { get; set; } public string ErrorProcedure { get; set; } public string ErrorMessage { get; set; } }
- 然后通过
FromSqlRaw调用存储过程并映射结果:
try { // 调用存储过程,注意参数要正确传递 var errorResults = await _context.Set<StoredProcedureError>() .FromSqlRaw("EXEC YourStoredProcedureName @InsertParam1, @InsertParam2", insertParam1, insertParam2) .ToListAsync(); // 如果有返回结果,说明存储过程执行出错了 if (errorResults.Any()) { var error = errorResults.First(); // 这里可以根据错误级别做不同处理,或者抛出自定义异常 throw new InvalidOperationException( $"存储过程 {error.ErrorProcedure} 执行失败,错误级别:{error.ErrorSeverity},错误信息:{error.ErrorMessage}" ); } } catch (Exception ex) { // 在这里捕获并处理异常 Console.WriteLine(ex.Message); }
方案2:修改存储过程抛出SQL异常,用ExecuteSqlRawAsync直接捕获
如果你更希望在C#端直接捕获SQL原生异常,不需要手动处理结果集,可以修改存储过程的Catch块,用THROW(推荐)或RAISERROR抛出异常,而不是返回SELECT结果:
存储过程修改后的代码:
BEGIN TRY -- 你的Insert操作 INSERT INTO YourTable (Column1, Column2) VALUES (@Val1, @Val2); END TRY BEGIN CATCH -- 直接抛出异常,而不是SELECT结果 THROW; -- 或者如果你需要自定义错误信息,可以这样写: -- DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(); -- DECLARE @ErrorSeverity INT = ERROR_SEVERITY(); -- THROW @ErrorSeverity, @ErrorMessage, 1; END CATCH
C#端捕获异常的代码:
try { await _context.Database.ExecuteSqlRawAsync( "EXEC YourStoredProcedureName @InsertParam1, @InsertParam2", insertParam1, insertParam2 ); } catch (SqlException ex) { // 从SqlException中获取错误信息 int errorSeverity = ex.Class; // 对应ERROR_SEVERITY()的返回值 string errorProcedure = ex.Procedure; string errorMessage = ex.Message; // 这里根据业务需求处理异常 Console.WriteLine($"存储过程 {errorProcedure} 执行失败,错误级别:{errorSeverity},错误信息:{errorMessage}"); }
总结
- 如果你的存储过程是通过
SELECT返回错误详情,必须用FromSqlRaw来获取结果集,再手动判断并处理错误; - 如果希望更简洁地在C#端捕获异常,修改存储过程抛出SQL异常,用
ExecuteSqlRawAsync就能直接捕获SqlException,从中提取错误级别、过程名和消息。
内容的提问来源于stack exchange,提问作者forwheeler
相关产品推荐
相关产品推荐

