AutoMapper项目忽略.Include的ProjectTo功能

4

我正在学习Automapper和EF Core,在尝试对基于导航属性计算的只读属性建模时,遇到了一个问题。 我的两个模型如下:

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;}
}

并尝试从父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. 

将此操作分成两个独立的步骤很容易:首先获取Parent,然后进行Mapper.Map。同时,如果更改Map如下,也可以正常工作:

cfg.CreateMap<Parent, VM>()
    .ForMember(d=>d.WantedCount, o => o.MapFrom(s=>s.Childs(c=>c.Type!=1));

但这样我将完全忽略模型中的只读属性。我想了解问题所在,以及如何解决它。

或者我甚至应该将计算某种方式移动到数据库端?但我想避免在数据库中存储此属性。

1个回答

6

ProjectTo是Auto Mapper中Queryable.Select的等效操作,因此生成的查询将进入EF Core的忽略包含关系类别。

像通常使用IQueryable<T>查询一样,您应该使用可映射到SQL的明确表达式,例如直接访问导航属性:

o.MapFrom(s => s.Childs.Count(c => c.Type != 1))

请注意,虽然这样会填充所需的WantedChildCount,但Include仍将被忽略。

那真是遗憾。我本来想在数据库层面进行映射操作的,看来我得想办法重构我的 *Count 属性,让其在数据库端进行计算。谢谢你的回答,我接受了它,因为它是正确的,而且我之前也有读到过相关内容。我问问题只是想找到替代方案... - soralex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接