【问题标题】:Entity Framework Eager Loading Filter实体框架急切加载过滤器
【发布时间】:2011-04-14 06:16:02
【问题描述】:

我有一个简单的查询,我想这样做:

1) ProductsChildProductsPriceTiers
2) 我想获取所有CategoryID 为1 且Display = true 的Products
3) 然后我想包括所有具有Display = true 的ChildProducts
4) 然后包括PriceTiersIsActive = 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)))

有什么建议吗?

【问题讨论】:

  • 为什么要针对同一个问题提出多个问题?而且你为什么要一次又一次地这样做?

标签: entity-framework eager-loading


【解决方案1】:

从下往上开始,意思是对 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

(注意:C# 中的priceTier => 与VB.NET 中的Function(priceTier) 相同)

MergeOption 在执行查询时最好设置为 other 而不是NoTracking。否则,EF 将无法确保在查询的结果集中多次出现的对象只物化一次,例如ProductChildProduct

不需要的结果: PriceTier 1 和 2 具有相同的父级,但父级已实现多次 - 每个 PriceTier 一次。

  • 产品1
    • 儿童产品 1
      • PriceTier 1
  • 产品1
    • 儿童产品 1
      • PriceTier 2

理想结果:MergeOption 设置为NoTracking 以外的任何值以获得这些结果:

  • 产品1
    • 儿童产品 1
      • PriceTier 1
      • PriceTier 2

【讨论】:

  • 从下往上开始会产生副作用,如果存在的父母没有任何与过滤器匹配的孩子,那么这些父母将不会出现在结果集中。您可以使用左连接来实现您的过滤
  • 5 年后,这仍然是 EF 的问题,您的答案仍然是最佳解决方案。谢谢!
【解决方案2】:

这里有一个解决方案,通过使用左连接而不是急切加载,并包括不存在过滤器子行的父行,让您的“行”与您的请求相匹配

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2012-02-07
    • 1970-01-01
    • 2012-09-10
    • 2011-05-03
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多