2011-04-14 103 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};