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

ASP.NET Core中DTO结合AutoMapper与Dapper时数据为空的问题

问题排查与修复方案

1. 检查DTO的属性定义

确保EmployeeDto的所有属性都具备公共的getter和setter——Dapper和AutoMapper都需要通过公共setter完成赋值操作。示例:

public class EmployeeDto
{
    public int Id { get; set; } // 必须同时包含get、set访问器
    public string Name { get; set; }
    public string Department { get; set; }
}

2. 修正Dapper的字段映射逻辑

如果数据库列名与DTO属性名不匹配(比如库表列是Emp_Name,DTO属性是Name),需要手动指定映射关系:

  • 方式一:用Dapper的Column特性标注DTO属性
public class EmployeeDto
{
    [Column("Emp_Id")]
    public int Id { get; set; }
    
    [Column("Emp_Name")]
    public string Name { get; set; }
}
  • 方式二:在查询SQL中给列取别名,匹配DTO属性名
SELECT Emp_Id AS Id, Emp_Name AS Name, Emp_Dept AS Department FROM Employees

3. 验证AutoMapper配置正确性

确认已正确创建Employee实体到EmployeeDto的映射规则:

  • 检查映射配置类,确保包含对应转换规则:
public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Employee, EmployeeDto>(); // 必须明确声明实体转DTO的映射
        // 若属性名不一致,需手动配置映射:
        // CreateMap<Employee, EmployeeDto>()
        //     .ForMember(dest => dest.Department, opt => opt.MapFrom(src => src.DeptName));
    }
}
  • 确保在Program.cs中注册了AutoMapper服务:
builder.Services.AddAutoMapper(typeof(MappingProfile));

4. 修正仓储层的DTO转换逻辑

确认仓储层中正确执行了实体到DTO的转换操作:

  • 错误示例(未做转换直接返回实体):
// 错误:返回Employee实体,但方法声明返回EmployeeDto,会导致隐式转换失败返回null
public async Task<EmployeeDto> GetEmployeeById(int id)
{
    var sql = "SELECT * FROM Employees WHERE Id = @Id";
    var employee = await _connection.QueryFirstOrDefaultAsync<Employee>(sql, new { Id = id });
    return employee;
}
  • 正确示例(使用AutoMapper显式转换):
public async Task<EmployeeDto> GetEmployeeById(int id)
{
    var sql = "SELECT * FROM Employees WHERE Id = @Id";
    var employee = await _connection.QueryFirstOrDefaultAsync<Employee>(sql, new { Id = id });
    return _mapper.Map<EmployeeDto>(employee); // 必须调用Map完成转换
}
  • 若直接用Dapper查询返回DTO,需保证SQL列名与DTO属性完全匹配:
public async Task<EmployeeDto> GetEmployeeById(int id)
{
    var sql = "SELECT Id, Name, Department FROM Employees WHERE Id = @Id";
    return await _connection.QueryFirstOrDefaultAsync<EmployeeDto>(sql, new { Id = id });
}

5. 清除缓存验证结果

如果使用了缓存服务,可能缓存了之前错误的null结果,需先清空缓存(比如重启服务、清除Redis缓存等),再重新测试接口。

6. 检查Response封装类逻辑

确保响应封装类正确处理了DTO对象,避免封装时意外将DTO置为null:

public class ApiResponse<T>
{
    public bool Success { get; set; }
    public T Data { get; set; } // 确保Data属性被正确赋值
    public string Message { get; set; }
}

// 控制器中正确封装响应:
[HttpGet("{id}")]
public async Task<ActionResult<ApiResponse<EmployeeDto>>> GetEmployee(int id)
{
    var dto = await _employeeRepo.GetEmployeeById(id);
    return Ok(new ApiResponse<EmployeeDto> { Success = true, Data = dto });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:22:13