In EF6 I was used to doing this:
var orders = GetAllEntities().Include(x => x.Contact.User);
if (includeProducts)
{
orders = orders.Include(x => x.ProductOrders.Select(y => y.RentStockOrders));
orders = orders.Include(x => x.ProductOrders.Select(y => y.Product));
orders = orders.Include(x => x.ProductOrders.Select(y => y.Currency));
orders = orders.Include(x => x.ProductOrders.Select(y => y.Coupons));
orders = orders.Include(x => x.AdditionalCosts);
orders = orders.Include(x => x.Partner);
orders = orders.Include(x => x.OrderCoupons.Select(y => y.Coupon.Partner));
if (includeStock)
{
orders = orders.Include(x => x.ProductOrders.Select(y => y.RentStockOrders.Select(z => z.Stock)));
}
}
if (includeInvoices)
{
orders = orders.Include(x => x.Invoices.Select(y => y.Attachments));
}
In EF Core it is not possible to override IQueryable
because it is more 'typesafe'
The first line returns a IIncludableQueryable<Order, User>
, so when I would do the second Include, it wants to make it something different, for example IIncludableQueryable<Ordr,User,ProductOrder>
I mostly have a GetByIdWithCrudRelations
which contains a set of bools to choose what to include and what not. sometimes it has only two, but in this case it has 8, which means it can have a lot of different outcomes if I would need to if-else everything.
Anyone got a clever solution for this?
You can use exactly the same pattern. Just start with IQueryable<T>
variable (note that IIncludableQueryable<T, P>
is still IQueryable<T>
with additional ThenInclude
support) and use ThenInclude
instead of nested Select
s:
IQueryable<Order> orders = GetAllEntities().Include(x => x.Contact.User);
// or var orders = GetAllEntities().Include(x => x.Contact.User).AsQueryable();
if (includeProducts)
{
orders = orders.Include(x => x.ProductOrders).ThenInclude(y => y.RentStockOrders);
orders = orders.Include(x => x.ProductOrders).ThenInclude(y => y.Product);
orders = orders.Include(x => x.ProductOrders).ThenInclude(y => y.Currency);
orders = orders.Include(x => x.ProductOrders).ThenInclude(y => y.Coupons);
orders = orders.Include(x => x.AdditionalCosts);
orders = orders.Include(x => x.Partner);
orders = orders.Include(x => x.OrderCoupons).ThenInclude(y => y.Coupon.Partner);
if (includeStock)
{
orders = orders.Include(x => x.ProductOrders).ThenInclude(y => y.RentStockOrders).ThenInclude(z => z.Stock);
}
}
if (includeInvoices)
{
orders = orders.Include(x => x.Invoices).ThenInclude(y => y.Attachments);
}
Note that since ThenInclude
chain is not nested, there is no need of different variable names x
, y
, z
etc. - single x
or similar would do the same.
Also since Include
is restarting the include chain from the root, the non conditional assignments like orders = orders.Include(...)
can be combined, e.g.
orders = orders
.Include(x => x.ProductOrders).ThenInclude(y => y.RentStockOrders)
.Include(x => x.ProductOrders).ThenInclude(y => y.Product)
.Include(x => x.ProductOrders).ThenInclude(y => y.Currency)
.Include(x => x.ProductOrders).ThenInclude(y => y.Coupons)
.Include(x => x.AdditionalCosts)
.Include(x => x.Partner)
.Include(x => x.OrderCoupons).ThenInclude(y => y.Coupon.Partner);
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