ADO.NET调用存储过程返回非零RETVAL时推荐抛出的异常类型
存储过程返回非零RETVAL时推荐抛出的异常类型
问题描述
我使用ADO.NET调用多个存储过程,其中大多数会返回RETVAL。目前当RETVAL非零时,我会抛出FaultException,但不确定这是否是最佳方案。我曾考虑过SqlException,但它没有公共构造函数,因此该方案不可行。请问当调用的存储过程返回非零值(表示执行失败)时,推荐抛出哪种异常?
现有遗留代码逻辑
public Employee GetEmployee(int id) { string reason = nameof(GetEmployee); try { DataTable dataTable; long retVal = ExecuteCommand("ps_getemployee", CommandType.StoredProcedure, out dataTable, true, CreateSqlParameter(parameterName: "id", value: id)); if (retVal != 0) { // 冗余代码:创建了3个新对象 throw new FaultException<FaultExceptionSvc>(new FaultExceptionSvc(null, reason, message: retVal.ToString(), faultNbr: errorCode, skipFrames: 2), new FaultReason(reason)); // 希望替换为更合适的异常类型 } return CreateEmployeeFromRow(dataTable.Rows[0]); } catch (FaultException<FaultExceptionSvc>) { throw; } catch (Exception ex) { throw CreateFaultException(ex, reason); } }
存储过程返回值片段
if @@error = 0 begin select @retval = 0 end else begin select @retval = -1 end
推荐方案
1. 自定义业务异常类
这是最灵活且符合.NET设计规范的方案,你可以创建一个继承自Exception的自定义异常,专门用于表示存储过程执行失败的业务错误:
public class StoredProcedureExecutionException : Exception { public long ReturnValue { get; } public int ErrorCode { get; } public StoredProcedureExecutionException(long returnValue, int errorCode, string message, Exception innerException = null) : base(message, innerException) { ReturnValue = returnValue; ErrorCode = errorCode; } }
替换原有抛出异常的代码:
if (retVal != 0) { throw new StoredProcedureExecutionException(retVal, errorCode, $"存储过程ps_getemployee执行失败,返回值:{retVal}"); }
该方案的优势:
- 语义清晰,一眼就能识别是存储过程执行失败的错误
- 可以携带自定义的返回值、错误码等上下文数据
- 符合.NET异常设计最佳实践,便于上层代码针对性捕获处理
2. 复用.NET内置通用异常
如果不想自定义异常,也可以选择合适的内置异常类型:
InvalidOperationException:适合表示操作处于无效状态时的错误,比如存储过程返回非零值意味着当前操作无法完成ApplicationException:用于应用程序特定错误,但微软官方更推荐自定义异常而非直接使用它
示例:
if (retVal != 0) { throw new InvalidOperationException($"存储过程ps_getemployee执行失败,返回值:{retVal}"); }
不推荐继续使用FaultException的原因
FaultException是专门为WCF服务设计的SOAP错误异常类型,如果你的项目不是WCF服务场景,使用它会导致语义不符,还会引入不必要的WCF依赖,增加代码复杂度。
内容的提问来源于stack exchange,提问作者Radek Strugalski
相关产品推荐
相关产品推荐

