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
相关产品推荐
相关产品推荐

