Dapper如何处理数据库返回的DBNull Dapper DBNull.Value转换方法

7次阅读

Dapper 默认将 DBNull.Value 映射为对应类型的默认值(如 int→0、int?→null),易掩盖空值问题;应优先使用可空类型,配合 TypeHandler、SQL COALESCE 或自定义映射安全处理 NULL。

Dapper 如何处理数据库返回的 DBNull Dapper DBNull.Value 转换方法

Dapper 默认会将数据库中的 DBNull.Value 映射为对应 .NET 类型的默认值(如 null0false),但这种 隐式转换 容易掩盖空值问题,尤其在可空类型(int?DateTime?)或自定义逻辑中需要显式区分 NULL 和默认值时。关键不是“怎么转”,而是“怎么安全地识别和处理”。

理解 Dapper 对 DBNull 的默认行为

Dapper 在填充实体时,对字段值做如下判断:

  • 如果数据库列值是 DBNull.Value,且目标属性是引用类型(如 stringMyClass),则赋值为 null
  • 如果是值类型(如 intDateTime),且未声明为可空(int?),Dapper 会尝试调用该类型的默认构造(如 default(int) → 0),** 不抛异常 **
  • 如果是可空值类型(int?DateTime?),DBNull.Value 会被正确映射为 null

手动检查 DBNull 的几种实用方式

当需要在映射前 / 后精确控制空值逻辑(比如记录日志、触发业务规则、统一转成特定默认值),推荐以下方法:

  • 使用查询时的 SQL COALESCE 或 CASE:在数据库层处理,例如 SELECT COALESCE(Price, 0) AS Price FROM Product,让 Dapper 始终收到非 null 值
  • 用 Query 配合 Func 自定义映射:在回调中手动判断 reader.IsDBNull(index),再决定赋值逻辑
  • 在实体属性的 setter 中拦截:配合私有 backing field,setter 内检查传入值是否为 DBNull.Value(需搭配 [SqlMapper.TypeHandler] 或自定义映射器)

推荐:用 TypeHandler 统一处理 DBNull(适合全局策略)

若项目中大量存在某类字段(如所有 decimal 字段都应转为 0m 而非 null),可注册自定义 TypeHandler

SqlMapper.AddTypeHandler(new DecimalTypeHandler()); // 实现示例:public class DecimalTypeHandler : SqlMapper.TypeHandler {public override void SetValue(IDbDataParameter parameter, decimal value) =>          parameter.Value = value;     public override decimal Parse(object value) =>          value == DBNull.Value ? 0m : Convert.ToDecimal(value); }

这样所有 decimal 列都会按你的规则解析,无需改实体或 SQL。

避免踩坑的注意事项

几个常见误区要避开:

  • 不要在实体中把值类型写成非可空却期望它接收 NULL —— Dapper 不会报错,但语义丢失(比如 int Age 收到 NULL 变成 0,无法区分“年龄未知”和“年龄为 0”)
  • 别依赖 == null 判断数据库 NULL —— 对非可空类型永远为 false;应优先用可空类型 + 显式 null 检查
  • 使用 QuerySingleOrDefault() 时注意:若查询无结果返回 default(T),这和 DBNull 是两回事,别混淆

基本上就这些。核心是:用可空类型承接可能为 NULL 的列,必要时用 TypeHandler 或 SQL 层统一兜底。不复杂但容易忽略细节。

星耀云
版权声明:本站原创文章,由 星耀云 2025-12-31发表,共计1482字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources