实体框架渴望加载筛选器



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

1( ProductsChildProductsPriceTiers
2( 我想得到所有具有CategoryID为1且Display=true的Products
3( 然后我想包括所有具有Display=true的ChildProducts
4( 然后包括具有IsActive=true的PriceTiers

根据我所读到的,EF不支持带过滤器的Eagle 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)))

有什么建议吗?

从下往上开始,意思是对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应设置为除NoTracking之外的其他。否则,EF将无法确保在查询结果集中多次出现的对象只具体化一次,例如ProductChildProduct:

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

  • 产品1
    • 儿童产品1
      • 价格Tier 1
  • 产品1
    • 儿童产品1
      • 价格Tier 2

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

  • 产品1
    • 儿童产品1
      • 价格Tier 1
      • 价格Tier 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};

最新更新