EF Core условно (добавить) включает в IQueryable - PullRequest
0 голосов
/ 07 мая 2018

В EF6 я привык к этому:

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));
}

В EF Core невозможно переопределить IQueryable, потому что он более «безопасен»

Первая строка возвращает IIncludableQueryable<Order, User>, поэтому, когда я делаю второе включение, оно хочет сделать его чем-то другим, например IIncludableQueryable<Ordr,User,ProductOrder>

У меня в основном есть GetByIdWithCrudRelations, который содержит набор bools для выбора, что включать, а что нет. иногда у него есть только два, но в этом случае у него есть 8, что означает, что у него может быть много разных результатов, если мне понадобится все остальное.

Кто-нибудь получил умное решение для этого?

1 Ответ

0 голосов
/ 07 мая 2018

Вы можете использовать точно такой же шаблон. Просто начните с переменной IQueryable<T> (обратите внимание, что IIncludableQueryable<T, P> по-прежнему IQueryable<T> с дополнительной поддержкой ThenInclude) и используйте ThenInclude вместо вложенных 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);
}

Обратите внимание, что поскольку цепочка ThenInclude не является вложенной, нет необходимости использовать разные имена переменных x, y, z и т. Д. - один x или аналогичный будет делать то же самое.

Кроме того, поскольку Include перезапускает цепочку включения из корня, можно комбинировать безусловные назначения, такие как orders = orders.Include(...), например,

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);
...