I a portion of my EF model that looks like this:
Summary:
Now, the query i'm trying to achieve:
Get information about Location Id 1234, including any Discussions and Comments associated with those Discussions.
I can get discussions and the comments like this:
var discussions = ctx.Posts
.OfType<Discussion>()
.Include(x => x.Comments)
.ToList();
But i can't seem to get it based on the Posts navigation on the Location entity.
I've tried this:
var locationWithDiscussionsAndComments = ctx
.Locations
.Include(x => x.Posts
.OfType<Discussion>()
.Select(y => y.Comments))
.SingleOrDefault();
Which compiles, but i get the error:
System.ArgumentException: The include path expression must refer to a property defined by the entity, optionally also with nested properties or calls to Select. Parameter name: path
Any ideas? I could probably go "backwards" from the Posts:
var locationWithDiscussionsAndComments = ctx
.Posts
.Include(x => x.Location)
.OfType<Discussion>()
.Include(x => x.Comments)
.Where(x => x.LocationId == 1234)
.Select(x => x.Location)
.ToList();
But that is both hairy and semantically wrong in terms of my repositories (i shouldn't have to go through a post repository to get information about a location).
Any ideas?
EDIT
So after having a bigger think about it, i realized that OfType<T>
is a filter operation. As as we know, EF does not support filtering with eager loading. The only options are retrieving everything, or using anonymous type projection.
No way i can retrieve everything, as there is far too much meta data involved. So i'm attempting the anonymous type projection.
Eager loading is the process whereby a query for one type of entity also loads related entities as part of the query. Eager loading is achieved by use of the Include method. For example, the queries below will load blogs and all the posts related to each blog. Include is an extension method in the System.
Eager loading means that the related data is loaded from the database as part of the initial query. Explicit loading means that the related data is explicitly loaded from the database at a later time.
Eager loading is achieved using the Include() method. In the following example, it gets all the students from the database along with its standards using the Include () method.
The Entity Framework Core (EF) extension method Include provides us the ability to load additional data besides the entities we are querying for. For example: loading products along with their translations. In some use cases we want to load all translations for the requested products and in some cases we don't.
The new Query method might help you:
var location = context.Locations.SingleOrDefault();
context.Entry(location)
.Collection(l => l.Posts)
.Query()
.OfType<Discussion>()
.Load();
We can add a new LoadProperty generic method to the Repository<T>
class that leverages this new QUery
method:
public void LoadProperty<TElement>(T entity,
Expression<Func<T, ICollection<TElement>>> navigationProperty,
Expression<Func<TElement, bool>> predicate) where TElement : class
{
_context.Set<T>().Attach(entity);
_context.Entry(entity)
.Collection(navigationProperty)
.Query()
.Where(predicate)
.Load();
}
Location location = _locationRepository.Find(1);
_locationRepository.LoadProperty(location, l => l.Posts, p => p is Discussion);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With