在C#中使用AutoMapper将DataReader数据映射到泛型类型的问题
解决AutoMapper从DataReader映射到泛型实体列表的问题
首先,你的当前代码存在几个关键问题:
- 错误使用
Mapper.CreateMap(还存在类型参数语法错误),AutoMapper的映射配置应该提前初始化,而非每次方法调用时临时创建; - 仅创建了映射配置,没有执行实际的映射操作,无法将中间结果转换为
List<TResult>; - 完全没必要先把DataReader数据转成
List<List<KeyValuePair<string, string>>>,AutoMapper支持直接从IDataReader映射到实体类型,能大幅简化代码逻辑。
下面是完整的修正方案:
第一步:配置AutoMapper Profile
先创建一个AutoMapper配置类,用来集中管理映射规则(默认情况下AutoMapper会自动匹配数据库列名和实体属性名,仅在名称不匹配时需要自定义配置):
public class DataMappingProfile : Profile { public DataMappingProfile() { // 示例:当实体属性名与数据库列名不一致时,添加自定义映射 // CreateMap<IDataReader, UserEntity>() // .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src["user_full_name"])) // .ForMember(dest => dest.RegisterTime, opt => opt.MapFrom(src => src["reg_timestamp"])); // 大部分场景下,AutoMapper会自动匹配列名与属性名,无需手动配置 } }
第二步:初始化AutoMapper
在应用启动阶段完成AutoMapper的初始化(根据项目类型选择方式):
.NET Core/.NET 6+ 依赖注入方式
var mapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile<DataMappingProfile>(); }); // 开发环境建议启用配置验证,提前发现映射问题 mapperConfig.AssertConfigurationIsValid(); // 将IMapper注册到依赖注入容器 services.AddSingleton<IMapper>(sp => mapperConfig.CreateMapper());
传统.NET Framework方式
var mapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile<DataMappingProfile>(); }); IMapper mapper = mapperConfig.CreateMapper(); // 可将mapper作为全局实例或通过构造函数注入到目标类中
第三步:重构LoadData方法
现在可以简化方法逻辑,直接用AutoMapper从DataReader映射到强类型实体列表:
// 通过构造函数注入IMapper private readonly IMapper _mapper; public YourServiceClass(IMapper mapper) { _mapper = mapper; } private async Task<List<TResult>> LoadData<TResult>(SqlConnection conn) { string sql = QueryForDuplicatesChecking; // 确保该SQL与TResult实体的字段匹配 using var command = new SqlCommand(sql, conn); using var reader = await command.ExecuteReaderAsync(); // AutoMapper直接将IDataReader映射为List<TResult> var result = _mapper.Map<List<TResult>>(reader); return result; }
关键说明
- AutoMapper的IDataReader原生支持:AutoMapper内置了对
IDataReader的映射能力,会自动读取列名并匹配实体属性(大小写不敏感,默认支持驼峰/帕斯卡命名匹配); - 避免冗余转换:跳过KeyValuePair中间环节,直接从DataReader映射到实体,减少内存开销和代码复杂度;
- 集中管理映射规则:所有映射配置统一放在Profile类中,后续新增实体或调整映射逻辑时,只需修改Profile即可,维护性更强;
- 强类型安全:泛型方法
LoadData<TResult>返回强类型列表,后续使用数据时无需手动转换,代码更严谨。
内容的提问来源于stack exchange,提问作者Meelfan Bmfp
相关产品推荐
相关产品推荐

