如何用Automapper的ProjectTo忽略嵌套嵌套对象并按需控制映射
实现方案
完全可以实现你的需求,无需创建Child类的副本,且能在SQL查询阶段就忽略目标字段,核心是利用AutoMapper的条件映射和投影上下文参数来区分两种映射场景。
具体步骤
1. 定义DTO结构
先确保你的DTO类保留ChildDTO的SomeObjects字段,无需额外创建精简版:
public class ParentDTO { public List<ChildDTO> Children { get; set; } } public class ChildDTO { public List<SomeObjectDTO> SomeObjects { get; set; } // Child的其他字段映射... } public class SomeObjectDTO { // SomeObject的字段映射... }
2. 配置AutoMapper映射规则
在映射Profile中,给Child -> ChildDTO的SomeObjects字段添加条件判断,仅当特定上下文参数不存在时才映射该字段:
public class AppMappingProfile : Profile { public AppMappingProfile() { // 基础映射:Child -> ChildDTO,默认保留SomeObjects CreateMap<Child, ChildDTO>() .ForMember(dest => dest.SomeObjects, opt => // 仅当上下文没有"IgnoreChildSomeObjects"标记时,才映射该字段 opt.Condition((src, dest, context) => !context.Items.ContainsKey("IgnoreChildSomeObjects"))); // Parent -> ParentDTO的映射,复用上面的Child映射规则 CreateMap<Parent, ParentDTO>(); } }
3. 调用投影映射时传递上下文参数
- 映射
Parent到ParentDTO时,传入上下文参数标记,触发忽略SomeObjects的逻辑:
// 映射Parent时忽略Child中的SomeObjects,SQL查询不会关联SomeObjects表 var parent = _mapper.ProjectTo<ParentDTO>( _dbContext.Parent.Where(c => c.Id == id), opt => opt.Items["IgnoreChildSomeObjects"] = true ).FirstOrDefault();
- 单独映射
Child到ChildDTO时,不传递该参数,默认保留SomeObjects:
// 单独映射Child时正常保留SomeObjects var child = _mapper.ProjectTo<ChildDTO>( _dbContext.Children.Where(c => c.Id == id) ).FirstOrDefault();
原理说明
AutoMapper的ProjectTo基于LINQ表达式树实现,会将映射规则直接转换为SQL查询语句。当添加条件映射后,SQL生成阶段就会跳过SomeObjects的关联查询,完全符合你"在SQL阶段忽略字段"的要求,而非事后删除对象。
内容的提问来源于stack exchange,提问作者ilyaVlad
相关产品推荐
相关产品推荐

