2011-04-14 96 views
5

我有一個簡單的查詢,我想這樣做:實體框架預先加載器

1)ProductsChildProducts具有PriceTiers
2)我想所有的Products有一個CategoryID 1和Display = true。
3)我想包括所有ChildProductsDisplay =真。
4)然後包含PriceTiersIsActive = true。

從我已閱讀,EF不支持預先加載有過濾器,所以下面將不工作:

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

有什麼建議?

+0

爲什麼你開始針對同一問題的多個問題?而且你爲什麼一次又一次地做呢? – 2011-04-14 08:25:29

回答

9

開始從下往上,意,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#是相同VB.NET Function(priceTier))執行查詢時

MergeOption最好應設置爲其他東西NoTracking。否則,EF將不能確保出現多次的結果集的查詢的一個目的是隻物化一次,如ProductChildProduct

不想要的結果: PriceTier 1和2具有相同的父母,但父母已經多次實現 - 每個PriceTier一次。

  • 產品1
    • ChildProduct 1
      • PriceTier 1
  • 產品1
    • ChildProduct 1
      • PriceTi ER 2

理想的結果: 設置MergeOptionNoTracking其他任何事情來得到這些結果:

  • 產品1
    • ChildProduct 1
      • PriceTier 1
      • PriceTier 2
+0

從底部開始會產生副作用,如果父母不存在任何與篩選條件相匹配的孩子,則這些父母不會在結果集中。您可以使用左連接來實現您的過濾 – 2014-10-29 15:28:03

+1

5年後,這仍然是EF的問題,您的答案仍然是最佳解決方案。謝謝! – urig 2017-02-20 18:09:38

0

這裏是一個解決方案,將讓你的「行」通過使用左,以符合您的要求加入的,而不是預先加載,並且包括父行,其中沒有孩子行存在的過濾器

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