Dapper读取大于decimal.MaxValue的数值时如何返回null避免查询失败
解决方案
有两种可行方案,均不需要修改数据库源数据,也能保留decimal类型的精度要求,异常数值自动返回null,下游系统无感知:
方案1:自定义Dapper类型映射(最推荐,全局生效无侵入)
Dapper支持自定义类型处理器,你可以直接重写decimal类型的解析逻辑,捕获超出范围的异常后返回null即可。
首先实现自定义TypeHandler:
public class SafeDecimalHandler : SqlMapper.TypeHandler<decimal?> { public override decimal? Parse(object value) { if (value == null || value == DBNull.Value) return null; try { return Convert.ToDecimal(value); } // 捕获超出decimal范围的溢出异常 catch (OverflowException) { // 可在这里加日志记录异常数值、对应行主键等信息,同步给客户排查上游问题 return null; } catch (InvalidCastException) { return null; } } public override void SetValue(IDbDataParameter parameter, decimal? value) { // 只读API不需要写操作,直接按原有逻辑赋值即可 parameter.Value = value ?? (object)DBNull.Value; } }
在API服务启动时全局注册这个处理器即可生效:
SqlMapper.AddTypeHandler(new SafeDecimalHandler());
- 无需修改任何现有查询代码,全局所有
decimal?类型的字段都会自动走安全转换逻辑 - 如果有非空
decimal字段的需求,可以单独实现非空decimal的Handler,解析失败时抛出自定义的业务异常,方便内部排查问题
方案2:SQL查询层面做范围校验
如果不想改动Dapper全局配置,可以在查询SQL中提前判断数值范围,超出范围的直接返回null:
Oracle中
decimal.MaxValue对应的数值为79228162514264337593543950335,最大支持28~29位有效数字,直接在查询中加判断即可:
SELECT CASE WHEN 待处理的数值字段 BETWEEN -79228162514264337593543950335 AND 79228162514264337593543950335 THEN 待处理的数值字段 ELSE NULL END AS 待处理的数值字段 FROM 业务表名
- 灵活度高,可以针对特定表、特定字段做针对性处理
- 缺点是需要逐个调整涉及大数值字段的查询语句
补充说明
原来Dapper抛出的column name is <null>错误是内部转换溢出时的异常捕获逻辑缺陷导致的,使用上述方案后可以完全避免该错误,整个查询流程不会中断。
内容的提问来源于stack exchange,提问作者Oblivious Sage
相关产品推荐
相关产品推荐

