Entity Framework Eager Загрузка фильтра - PullRequest
5 голосов
/ 14 апреля 2011

У меня есть простой запрос, который я хочу сделать так:

1) Products имеют ChildProducts, которые имеют PriceTiers
2) Я хочу получить все Products, которые имеют Category с ID, равным 1 и Display = true.
3) Я хочу затем включить все ChildProducts, которые имеют Display = true.
4) А затем включите PriceTiers, которые имеют IsActive = true.

Из того, что я прочитал, EF не поддерживает Eager Loading с фильтрами, поэтому следующее не будет работать:

ProductRepository.Query.IncludeCollection(Function(x) x.ChildProducts.Where(Function(y) y.Display).Select(Function(z) z.PriceTiers.Where(Function(q) q.IsActive))).Where(Function(x) x.Categories.Any(Function(y) y.ID = ID)))

Есть предложения?

Ответы [ 2 ]

9 голосов
/ 14 апреля 2011

Начните снизу вверх, то есть примените фильтр к объекту PriceTier и его родителям и включите его родителей (C # извините, но, надеюсь, вы поняли):

repository.PriceTiers
  .Include("ChildProduct.Product") // eager load parents
  .Where(priceTier => 
    priceTier.IsActive &&
    priceTier.ChildProduct.Display &&
    priceTier.ChildProduct.Product.ID == 1 &&
    priceTier.ChildProduct.Product.Display)
  .AsEnumerable() // execute SQL statement
  .Select(priceTier => 
    priceTier.ChildProduct.Product) // return products rather than price tiers

(Примечание: priceTier => в C # совпадает с Function(priceTier) в VB.NET)

MergeOption в идеале должно быть установлено на что-то другое , чем NoTracking при выполнении запроса. В противном случае EF не будет гарантировать, что объект, который появляется несколько раз в наборе результатов запроса, материализуется только один раз, например Product или ChildProduct:

Нежелательные результаты: PriceTier 1 и 2 имеют одинаковых родителей, но родители материализуются несколько раз - один раз для каждого PriceTier.

  • Продукт 1
    • ChildProduct 1
      • PriceTier 1
  • Продукт 1
    • ChildProduct 1
      • PriceTier 2

Идеальные результаты: Установите MergeOption на любое значение, отличное от NoTracking, чтобы получить следующие результаты:

  • Продукт 1
    • ChildProduct 1
      • PriceTier 1
      • PriceTier 2
0 голосов
/ 29 октября 2014

вот решение, которое предоставит ваши «строки» для соответствия вашему запросу, используя левые объединения вместо быстрой загрузки, и включая родительские строки, где для фильтров не существует дочерних строк

var query = from product in Products
                join child_ in ChildProducts on product equals child_.Product into child_join
                from child in child_join.DefaultIfEmpty()
                join tier_ in PriceTiers on child equals tier_.ChildProduct into tier_join
                from tier in tier_join.DefaultIfEmpty()
                where product.Display && product.Category.ID == 1
                where child == null || child.Display
                where tier == null || tier.IsActive
                select new {product, child, tier};
...