使用ABP Dapper解析ExtraProperties时遇类型转换错误求助
Dapper映射ExtraPropertyDictionary失败的解决方法
问题场景
执行全表查询代码时抛出转换异常:
(dbConnection.QueryAsync("select * from AbpUsers", transaction: await GetDbTransactionAsync())).ToList()
异常信息:
System.Data.DataException: 'Error parsing column 2 (ExtraProperties={} - String)'
InvalidCastException: Invalid cast from 'System.String' to 'Volo.Abp.Data.ExtraPropertyDictionary'
但单独查询ExtraProperties列时代码正常:
(dbConnection.QueryAsync("select ExtraProperties from AbpUsers", transaction: await GetDbTransactionAsync())).ToList()
原因分析
数据库中ExtraProperties存储的是JSON字符串,而实体类(如IdentityUser)中该属性类型为ExtraPropertyDictionary。单独查询时Dapper直接返回字符串,不会触发类型转换;全表查询时Dapper尝试自动映射实体类,但缺少字符串到ExtraPropertyDictionary的转换逻辑,导致失败。
解决办法
1. 全局注册Dapper类型转换器
编写自定义类型转换器,让Dapper处理字符串与ExtraPropertyDictionary的双向转换:
using Dapper; using Newtonsoft.Json; using Volo.Abp.Data; public class ExtraPropertyDictionaryTypeHandler : SqlMapper.TypeHandler<ExtraPropertyDictionary> { public override ExtraPropertyDictionary Parse(object value) { if (value is string json) { return string.IsNullOrEmpty(json) ? new ExtraPropertyDictionary() : JsonConvert.DeserializeObject<ExtraPropertyDictionary>(json); } return new ExtraPropertyDictionary(); } public override void SetValue(System.Data.IDbDataParameter parameter, ExtraPropertyDictionary value) { parameter.Value = JsonConvert.SerializeObject(value); } } // 在应用启动时注册(比如Program.cs或Startup.cs) SqlMapper.AddTypeHandler(new ExtraPropertyDictionaryTypeHandler());
2. 查询时手动映射
如果不需要全局转换,可在查询后手动转换属性:
var queryResult = await dbConnection.QueryAsync("select * from AbpUsers", transaction: await GetDbTransactionAsync()); var users = queryResult.Select(row => new IdentityUser { Id = row.Id, UserName = row.UserName, Email = row.Email, // 映射其他属性 ExtraProperties = JsonConvert.DeserializeObject<ExtraPropertyDictionary>(row.ExtraProperties.ToString()) }).ToList();
3. 确认实体类属性配置
确保IdentityUser中的ExtraProperties属性已正确定义为ExtraPropertyDictionary类型,无需额外特性(Dapper不依赖ABP框架特性)。
内容的提问来源于stack exchange,提问作者Quyết Vũ Văn
相关产品推荐
相关产品推荐

