I'm learning Automapper, and EF Core, and stumbled onto a problem, while trying to model get-only property, which is calculated based on navigation property. I'm having two models:
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;}
}
One DTO:
public class VM
{
public string Name{get;set;}
public int WantedCount{get;set;}
}
And trying to automap VM from Parent like:
var c = context.Parents.Include(p => p.Childs).ProjectTo<VM>().FirstOrDefault();
Automapper configured like this:
Mapper.Initialize(cfg=>
cfg.CreateMap<Parent, VM>()
.ForMember(d=>d.WantedCount, o => o.MapFrom(s=>s.WantedChildCount));
The problem is that in resulting VM field WantedCount isn't populated. In logs I've found message
The Include operation for navigation: 'p.Childs' was ignored because the target navigation is not reachable in the final query results.
It's easy so split this operation into two separate: first take Parent, and then Mapper.Map. Also, it could work when changing Map like this:
cfg.CreateMap<Parent, VM>()
.ForMember(d=>d.WantedCount, o => o.MapFrom(s=>s.Childs(c=>c.Type!=1));
But this way I'll ignore get-only property in model totally. I'd like to understand what the problem is, and how could I solve it.
Or maybe I should even somehow move calculation to DB side? But I'd like to avoid storing this property in database.
ProjectTo
is the Auto Mapper equivalent of Queryable.Select
, hence the resulting query fall into EF Core Ignored Includes category.
As usual with IQuerable<T>
queries, you should use explicit expression which can be mapped to SQL, e.g. something like this accessiong directly the navigation property
o.MapFrom(s => s.Childs.Count(c => c.Type != 1))
Note that while this should populate the desired WantedChildCount
, the Include
will still be ignored.