AutoMapper搭配EF Core查询嵌套属性等于指定值报错如何解决
问题根因
异常由两层类型不匹配冲突导致:
- 实体类
ParentThing的ChildThingId为可空类型int?,对应的导航属性Child允许为null,但DTO层ChildDTO.Id声明为不可空int、ParentDTO.Child也未声明为可空,AutoMapper将e.Child.Id == id的DTO属性访问表达式转换为SQL可识别的实体表达式时,出现可空与不可空类型的匹配错误。 - 手动将
id转为int?后,AutoMapper内部的表达式重写逻辑不允许隐式修改已声明成员的类型,因此抛出重写禁止异常。
解决方案
不需要扁平化嵌套属性,可任选以下一种方案解决:
方案1(最推荐):将过滤逻辑放在投影之前执行
直接针对EF原生实体做过滤,不存在表达式转换的兼容问题,查询性能最优:
var dtos = dbSet .Where(p => p.Child.Id == id) .ProjectTo<ParentDTO>(mapper.ConfigurationProvider) .ToList();
方案2:调整DTO可空性与实体对齐
如果业务需要在投影后执行过滤,修改DTO定义匹配实体的可空规则即可:
public class ParentDTO { public string Name { get; set; } public ChildDTO? Child { get; set; } // 和实体导航属性的可空性保持一致 }
如果业务逻辑能保证Child一定不为null,也可以在AutoMapper映射配置中显式声明,避免类型推断错误:
CreateMap<ParentThing, ParentDTO>() .ForMember(d => d.Child, opt => opt.MapFrom(s => s.Child!));
方案3:过滤时增加显式null检查
不修改现有定义的前提下,在投影后的过滤条件中先判断Child不为null即可:
var dtos = mapper.ProjectTo<ParentDTO>(dbSet) .Where(e => e.Child != null && e.Child.Id == id) .ToList();
内容的提问来源于stack exchange,提问作者WaitsAtWork
相关产品推荐
相关产品推荐

