I have a .Net Core 2.2 project with EntityFramework and a model with many nested properties either single object or collections.
I've enabled lazy loading and now I want selectively load only the parts of the object tree I'm insterested in in my controller.
When I use .Include() everything is fine until I want to include a collection property and for every item in that collection I want to include a related entity.
Reading the documentation I used this approach:
var mainObj = _db.MyEntityA.AsNoTracking()
.Include(e => e.MyEntityB)
.Include(e => e.CollectionOfEntityC.Select((MyEntityC ce) => ce.MyEntityD))
When I run it it gives something like this:
InvalidOperationException: The Include property lambda expression 'e => {from EntityC ce in e.CollectionOfEntityC select [ce].MyEntityD}' is invalid. The expression should represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, specify an explicitly typed lambda parameter of the target type, E.g. '(Derived d) => d.MyProperty'.
So I've tried to add the cast:
var mainObj = _db.MyEntityA.AsNoTracking()
.Include(e => e.MyEntityB)
.Include(e => e.CollectionOfEntityC.Select((MyEntityC ce) => ce.MyEntityD))
But nothing changes.
I've tried to use .ThenInclude() this way:
var mainObj = _db.MyEntityA.AsNoTracking()
.Include(e => e.MyEntityB)
.ThenInclude(e => e.Select((MyEntityC ce) => ce.MyEntityD))
With or without the cast, nothing changes.
Finally, reasonably, if I remove that navigation property, it gives me this exception:
Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.DetachedLazyLoadingWarning: An attempt was made to lazy-load navigation property 'MyEntityD' on detached entity of type 'MyEntityCProxy'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking()'.
This same scenario, worked as expected on the EF for the .Net Framework, form which I'm porting to .Net Core.
EDIT:
Exploring the correctly mentioned duplicates, I just wanted to add few more related aspects.
@StriplingWarrior answer below is good; I fixed my code using .ThenInclude() instead of .Select(); now everything builds, but:
- IntelliSense doesn't help writing the code inside ThenInclude()
- if I leave
AsNoTraking()
I must disable theDetachedLazyLoadingWarning
- if I remove
AsNoTracking()
EF tracks changes I don't want it to track (I want a readonly snapshot of a complex object)