使用AutoMapper映射嵌套属性时CustomerName为空的问题排查
问题描述
我有互相关联的Customer和Sale两张表,尝试将Sale实体映射到SaleDto以展示客户名称。已定义实体类和DTO,配置AutoMapper将Sale.Customer.Name映射到SaleDto.CustomerName,但调用API后返回的CustomerName为null,请求解决该问题。
相关代码如下:
Customer 实体类
public class Customer { public int Id { get; set; } public string Name { get; set; } public ICollection<Sale>? Sales { get; set; } }
Sale 实体类
public class Sale { public int Id { get; set; } public int CustomerId { get; set; } public DateTime? Created { get; set; } public Customer? Customer { get; set; } public ICollection<SaleOrder>? SaleOrders { get; set; } }
SaleDto
public class SaleDto { public int Id { get; set; } public int CustomerId { get; set; } public string CustomerName { get; set; } public DateTime? Created { get; set; } }
AutoMapper 配置
public MappingProfiles() { CreateMap<Sale, SaleDto>() .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name)); }
API 代码
[HttpGet] [ProducesResponseType(200, Type = typeof(IEnumerable<Sale>))] public IActionResult GetSales() { var sales = _mapper.Map<List<SaleDto>>(_saleRepository.GetSales()); if (!ModelState.IsValid) return BadRequest(ModelState); return Ok(sales); }
返回结果
[ { "id": 1, "customerId": 1, "customerName": null, "amount": 2325, "created": "2023-07-10T22:25:49.3510244" } ]
解决方案
问题核心是EF Core未加载Sale实体关联的Customer导航属性,导致映射时src.Customer为null,最终CustomerName取不到值。提供两种解决思路:
1. 显式加载关联属性(推荐)
修改仓储中的GetSales方法,使用Include强制加载Customer:
public IEnumerable<Sale> GetSales() { return _context.Sales.Include(s => s.Customer).ToList(); }
若使用异步查询,对应改为Include(s => s.Customer).ToListAsync()。
2. 启用延迟加载(按需选择)
如果项目场景适合延迟加载,可在EF上下文配置中开启:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的数据库连接字符串") .UseLazyLoadingProxies(); }
同时需将Sale实体中的Customer属性改为virtual:
public virtual Customer? Customer { get; set; }
注意:延迟加载可能引发N+1查询问题,需根据业务场景评估使用。
额外优化:空值防护
为避免Customer为null时抛出异常,可在AutoMapper映射中添加空值判断:
CreateMap<Sale, SaleDto>() .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer?.Name ?? string.Empty));
内容的提问来源于stack exchange,提问作者user22219327
相关产品推荐
相关产品推荐

