.NET中如何仅捕获SQL Server RAISERROR异常 忽略存储过程PRINT消息
解决方案
核心原理
SQL Server的消息有明确的严重性等级划分:
PRINT输出、以及RAISERROR指定严重性等级≤10的消息,属于信息性/警告类消息,默认不会被ADO.NET识别为异常抛出- 只有
RAISERROR指定严重性等级≥11的消息,才会作为SqlException抛出,进入C#的catch块
你遇到的PRINT消息被捕获的问题,大概率是代码中主动将SqlConnection的FireInfoMessageEventOnUserErrors属性设为了true,导致所有SQL侧消息都被转为异常抛出。
方案1:适配默认规范(优先推荐)
不需要修改现有捕获逻辑的大结构,仅做两处调整即可:
- 存储过程中需要抛错被C#捕获的场景,
RAISERROR指定严重性等级≥11,示例:
-- 16是SQL Server默认的用户自定义错误级别,符合常规业务场景使用 RAISERROR('业务错误提示', 16, 1)
- 保持
SqlConnection的FireInfoMessageEventOnUserErrors为默认值false,此时PRINT消息、低级别通知消息不会进入catch块,仅会触发SqlConnection.InfoMessage事件,可单独订阅处理不需要抛给用户的通知内容。
方案2:无法修改存储过程时的兼容方案
如果没有权限调整存储过程逻辑,可修改C#捕获逻辑,通过SqlException的Class属性过滤异常类型:
try { // SQL调用相关代码 } catch (SqlException sqlEx) { // Class属性对应SQL Server消息的严重性等级,仅处理≥11级的错误(即RAISERROR抛出的异常) if (sqlEx.Class >= 11) { return BadRequest(sqlEx.Message); } // 低于11级的消息(含PRINT输出)直接忽略 } catch (Exception e) { // 其他非SQL类型的异常处理 return BadRequest(e.Message); }
内容的提问来源于stack exchange,提问作者Anthino Russo
相关产品推荐
相关产品推荐

