我在学习Automapper和EF Core时偶然发现了一个问题,同时尝试建模基于导航属性计算的get-only属性。 我有两个模特:
public class Parent
{
public int Id {get;set;}
public string Name {get;set;}
public ICollection<Child> Childs {get;set;}
public int WantedChildCount {get{return Childs?.Count(c=>c.Type!=1)??0;}
}
public class Child
{
public int Id {get;set;}
public string Name {get;set;}
public int Type {get;set;}
}
一个DTO:
public class VM
{
public string Name{get;set;}
public int WantedCount{get;set;}
}
尝试从Parent中自动执行VM,如:
var c = context.Parents.Include(p => p.Childs).ProjectTo<VM>().FirstOrDefault();
Automapper配置如下:
Mapper.Initialize(cfg=>
cfg.CreateMap<Parent, VM>()
.ForMember(d=>d.WantedCount, o => o.MapFrom(s=>s.WantedChildCount));
问题在于,在生成的VM字段中,没有填充WantedCount。在日志中我找到了消息
The Include operation for navigation: 'p.Childs' was ignored because the target navigation is not reachable in the final query results.
这很简单,所以将此操作拆分为两个单独的:首先取父素,然后取Mapper.Map。 此外,它可以在更改地图时起作用:
cfg.CreateMap<Parent, VM>()
.ForMember(d=>d.WantedCount, o => o.MapFrom(s=>s.Childs(c=>c.Type!=1));
但是这样我完全忽略了模型中的get-only属性。 我想了解问题所在,我该如何解决。
或者我甚至可能以某种方式将计算移到DB端?但我想避免将此属性存储在数据库中。
答案 0 :(得分:2)
ProjectTo
是自动映射器等效于Queryable.Select
,因此生成的查询属于EF Core Ignored Includes类别。
与IQuerable<T>
查询一样,您应该使用可以映射到SQL的显式表达式,例如:像这样的东西直接导航属性
o.MapFrom(s => s.Childs.Count(c => c.Type != 1))
请注意,虽然这应填充所需的WantedChildCount
,但仍会忽略Include
。