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