You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AutoMapper未填充数据:Web API Core异步项目问题求助

AutoMapper映射SqlDataReader到Student时属性未填充的解决方法

问题场景

在ASP.NET Core Web API异步项目中,使用AutoMapper将SqlDataReader映射到Student实体,程序无报错且能返回Student实例,但所有属性均未被填充,已确认SqlDataReader包含有效数据。

核心原因

  1. SqlDataReader未指向有效行:SqlDataReader初始状态位于结果集起始位置(未指向任何行),直接调用Map方法无法读取数据。
  2. 缺少DataReader映射支持:AutoMapper默认未启用针对DataReader的映射逻辑,需显式配置相关扩展。
  3. 重复创建Mapper实例:每次调用InitializeAutomapper()都会生成新的Mapper实例,既低效也可能隐藏配置问题。

解决方案

1. 先读取Reader行再映射(基础修复)

在调用AutoMapper的Map方法前,必须先调用ReadAsync()将Reader指针移动到有效数据行:

using (var reader = await cmd.ExecuteReaderAsync())
{
    if (await reader.ReadAsync()) // 移动到第一行数据
    {
        ret = ModelUtils.InitializeAutomapper().Map<Student>(reader);
    }
}

2. 启用AutoMapper DataReader扩展(推荐)

安装专门处理DataReader的AutoMapper扩展包:

dotnet add package AutoMapper.Data

修改ModelUtils中的映射配置,添加DataReader支持并验证配置有效性:

using AutoMapper;
using AutoMapper.Data;
using System.Data;

namespace WebAPI.Models
{
    public class ModelUtils
    {
        public static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.AddDataReaderMapping(); // 启用DataReader映射支持
                cfg.CreateMap<IDataReader, Student>(); // 使用IDataReader提升通用性
            });

            config.AssertConfigurationIsValid(); // 验证映射配置,提前发现错误
            return new Mapper(config);
        }
    }
}

3. 全局注册Mapper实例(最佳实践)

避免重复创建Mapper实例,在Program.cs中将AutoMapper注册为全局服务:

builder.Services.AddAutoMapper(cfg =>
{
    cfg.AddDataReaderMapping();
    cfg.CreateMap<IDataReader, Student>();
}, typeof(Program));

修改Student类,通过依赖注入获取IMapper实例:

using System.Data;
using System.Data.SqlClient;
using AutoMapper;

namespace WebAPI.Models
{
    public class Student
    {
        private readonly IMapper _mapper;

        // 构造函数注入IMapper
        public Student(IMapper mapper)
        {
            _mapper = mapper;
        }

        public int StudentID { get; set; }
        public string StudentFirstName { get; set; } = string.Empty;
        public string StudentLastName { get; set; } = string.Empty;

        public async Task<Student> GetStudentByID(string conn, int studentID)
        {
            using (var connection = new SqlConnection(conn))
            {
                var cmd = new SqlCommand("Core.StudentByID_Get", connection);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("StudentID", studentID);
                await connection.OpenAsync();
                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (await reader.ReadAsync())
                    {
                        return _mapper.Map<Student>(reader);
                    }
                }
            }
            return new Student(_mapper); // 返回空实例或根据需求处理
        }
    }
}

4. 处理命名不匹配的情况

如果数据库列名与实体属性名不一致(比如列名为Student_FirstName,属性为StudentFirstName),需要显式配置字段映射:

cfg.CreateMap<IDataReader, Student>()
   .ForMember(dest => dest.StudentFirstName, opt => opt.MapFrom(src => src["Student_FirstName"]))
   .ForMember(dest => dest.StudentLastName, opt => opt.MapFrom(src => src["Student_LastName"]));

内容的提问来源于stack exchange,提问作者Steve Olson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:34:59