C
C#12mo 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
FestivalDelGelato
you can use .Include(_ => (_ as InternalAccommodation).PriceDetails)
linqisnice
linqisniceOP12mo ago
hmm yeah that might be cleaner, but then I have to suppress the null warning on the cast
FestivalDelGelato
yeah the warning is a little bothering
linqisnice
linqisniceOP12mo ago
could place the switch in its own class and namespace and use pragma warning disable lol
FestivalDelGelato
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
linqisniceOP12mo 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
FestivalDelGelato
seems a quite wild query why is not PriceDetails in CoreProduct?
linqisnice
linqisniceOP12mo ago
beacuse different products have different price details
FestivalDelGelato
and why a single query is trying to extract such heterogeneous objects/relations?

Did you find this page helpful?