AutoMapper如何映射多层嵌套对象的属性?
嗨,看你遇到的问题,核心其实不是AutoMapper的配置错了,而是你的实体关联数据没正确加载导致的!我来给你拆解下解决方案:
问题根源
你代码里的virtual属性是EF Core用来实现延迟加载的标记,但如果在查询ResearcherInvolved的时候,没有主动加载关联的User和Person,那src.User.Person就会是null,AutoMapper自然拿不到Name和Surname的值。你之前尝试加Include没生效,大概率是Include的方式不对。
解决方案1:正确加载关联数据(推荐)
在查询ResearcherInvolved时,用Include + ThenInclude来逐层加载嵌套的关联对象,这样查询出来的实体就会包含完整的User和Person数据,AutoMapper就能正常映射了。示例代码如下:
// 假设你用EF Core查询数据 var researcher = _dbContext.ResearcherInvolved .Include(r => r.User) // 加载关联的User对象 .ThenInclude(u => u.Person) // 接着加载User关联的Person对象 .FirstOrDefault(r => r.UserId == targetUserId);
把查询出来的这个researcher传给AutoMapper映射,就能拿到正确的Name和Surname了。
解决方案2:添加空值保护(避免异常)
如果暂时没法修改查询逻辑,或者担心出现空引用异常,可以在AutoMapper映射配置里用C#的空传播运算符?.,这样就算User或Person是null,也不会抛异常,只是返回null(但如果数据加载正常的话,还是能拿到值的):
CreateMap<ResearcherInvolved, ResearcherInvolvedDto>() .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.User?.Person?.Name)) .ForMember(dest => dest.Surname, opt => opt.MapFrom(src => src.User?.Person?.Surname));
补充:关于virtual属性的小知识
那些virtual是EF Core的延迟加载开关,当你访问这些属性时,EF会自动去数据库拉取关联数据,但前提是你的DbContext还处于活跃状态。如果DbContext已经被释放,延迟加载就会失败,导致属性为null。所以更可靠的方式还是主动用Include提前加载需要的关联数据,不要依赖延迟加载。
备注:内容来源于stack exchange,提问作者Amon Dvachovski

