我有一个简单的查询,我想这样做:
1( Products
有ChildProducts
有PriceTiers
2( 我想得到所有具有Category
且ID
为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将无法确保在查询结果集中多次出现的对象只具体化一次,例如Product
或ChildProduct
:
不需要的结果:PriceTier 1和2具有相同的父级,但父级已实现多次——每个PriceTier一次。
- 产品1
- 儿童产品1
- 价格Tier 1
- 儿童产品1
- 产品1
- 儿童产品1
- 价格Tier 2
- 儿童产品1
理想结果:将MergeOption
设置为NoTracking
以外的任何值以获得以下结果:
- 产品1
- 儿童产品1
- 价格Tier 1
- 价格Tier 2
- 儿童产品1
这里有一个解决方案,它将通过使用左联接而不是急切加载来为您的"行"提供匹配您的请求,并包括过滤器不存在子行的父行
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};