C
C#14mo ago
linqisnice

Polymorphic query handling in EF Core - Thoughts?

So I'm having to deal a lot with entity polymorphism and querying the db to avoid having to execute multiple separate queries. I'm not sure about best practices here, but i also have to eagerload certain nav props from the derived types. Anyone know a better way than this?
private async Task<IReadOnlyList<CoreProduct>> GetCoreProducts(IEnumerable<IProductRequest> requests, int internalPropertyId)
{
var query = _dbContext.Products.OfType<CoreProduct>().AsSplitQuery();

foreach(var request in requests.GroupBy(x => x.GetType(), x => x))
{
query = request switch
{
IAccommodationRequest => AccommodationQuery(query),
// more types here
_ => throw new UnreachableException()
};
}

return await query.Where(x => x.InternalPropertyId == internalPropertyId && requests.Select(x => x.ProductId).Contains(x.Id)).ToListAsync();
}

private IQueryable<CoreProduct> AccommodationQuery(IQueryable<CoreProduct> query)
=> query = query.OfType<InternalAccommodation>().Include(x => x.PriceDetails);
private async Task<IReadOnlyList<CoreProduct>> GetCoreProducts(IEnumerable<IProductRequest> requests, int internalPropertyId)
{
var query = _dbContext.Products.OfType<CoreProduct>().AsSplitQuery();

foreach(var request in requests.GroupBy(x => x.GetType(), x => x))
{
query = request switch
{
IAccommodationRequest => AccommodationQuery(query),
// more types here
_ => throw new UnreachableException()
};
}

return await query.Where(x => x.InternalPropertyId == internalPropertyId && requests.Select(x => x.ProductId).Contains(x.Id)).ToListAsync();
}

private IQueryable<CoreProduct> AccommodationQuery(IQueryable<CoreProduct> query)
=> query = query.OfType<InternalAccommodation>().Include(x => x.PriceDetails);
9 Replies
this_is_pain
this_is_pain14mo ago
you can use .Include(_ => (_ as InternalAccommodation).PriceDetails)
linqisnice
linqisniceOP14mo ago
hmm yeah that might be cleaner, but then I have to suppress the null warning on the cast
this_is_pain
this_is_pain14mo ago
yeah the warning is a little bothering
linqisnice
linqisniceOP14mo ago
could place the switch in its own class and namespace and use pragma warning disable lol
this_is_pain
this_is_pain14mo ago
it doesn't look to me that you really need thet switch i mean it depends on how you want to organize the code
linqisnice
linqisniceOP14mo ago
ur probably right, at that point its just building the query and it doesn't impact performance either way if none of those requests are materialized if they don't exist
this_is_pain
this_is_pain14mo ago
seems a quite wild query why is not PriceDetails in CoreProduct?
linqisnice
linqisniceOP14mo ago
beacuse different products have different price details
this_is_pain
this_is_pain14mo ago
and why a single query is trying to extract such heterogeneous objects/relations?

Did you find this page helpful?