Dapper中Query与GetList查询返回结果不一致问题求助
问题分析与解决方案
这问题我之前做PostgreSQL+Dapper项目时也碰到过,核心是Dapper原生映射与扩展方法的类型处理差异,结合你的代码和场景,咱们拆解下原因和解决办法:
为什么会出现两种查询结果差异?
你的数据库字段和实体类型存在不匹配:
- 数据库中
scheduled_task_id是serial(PostgreSQL里等价于integer,32位整数),scheduled_task_type_id是int(同样32位) - 但实体类里对应的字段是
long?(64位可空整数)
Dapper的原生Query<T>方法对类型匹配要求很严格,当数据库返回的是32位int,而实体是64位long?时,它不会自动做隐式转换,导致映射失败,所以这两个字段返回null。
而你用的GetList<T>(应该是Dapper Extensions这类扩展库的方法)内部做了更智能的类型适配,会自动处理这种小范围整数到大范围可空类型的转换,所以能正确返回完整数据。
解决办法(任选其一即可)
1. 调整实体字段类型,和数据库保持一致
最直接的方式是把实体里的两个可空字段改成int?,和数据库的int/serial类型匹配:
[Table("scheduled_task")] public class DOScheduledTask { [Key] [Column("scheduled_task_id")] public int? ScheduledTaskId { get; set; } // 从long?改为int? [Column("description")] public string Description { get; set;} [Column("predicate")] public string Predicate { get; set; } [Column("path")] public string Path { get; set; } [Column("scheduled_task_type_id")] public int? ScheduledTaskTypeId { get; set; } // 从long?改为int? }
改完后再用Query<T>查询,就能正常映射了。
2. 在SQL查询中显式转换字段类型
如果不想修改实体类,可以在查询SQL里把int类型转成bigint,让Dapper能映射到long?:
select scheduled_task_id::bigint, description, predicate, path, scheduled_task_type_id::bigint from scheduled_task;
3. 自定义Dapper类型处理器(全局生效)
如果项目里有很多类似的int转long?的场景,可以写一个全局的类型处理器,让Dapper自动处理这种转换:
public class IntToLongNullableHandler : SqlMapper.TypeHandler<long?> { public override void SetValue(IDbDataParameter parameter, long? value) { parameter.Value = value.HasValue ? (int)value.Value : DBNull.Value; } public override long? Parse(object value) { if (value is int intValue) { return (long)intValue; } return null; } } // 在项目初始化的地方注册这个处理器(比如Startup.cs) SqlMapper.AddTypeHandler(new IntToLongNullableHandler());
注册后,所有long?类型的字段碰到数据库返回的int值,都会自动转换,不用再单独处理。
内容的提问来源于stack exchange,提问作者WynDiesel
相关产品推荐
相关产品推荐

