我想做一个简单的查询:
1)Products
ChildProducts
PriceTiers
有Products
2)我希望得到Category
ID
Display
为1且ChildProducts
=真的所有Display
。
3)然后我想要包含PriceTiers
= true的所有IsActive
4)然后包含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)))
= true。{/ p>的{{1}}
根据我的阅读,EF不支持使用过滤器进行预先加载,因此以下内容不起作用:
{{1}}
有什么建议吗?
答案 0 :(得分: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
(注意:C#中的priceTier =>
与VB.NET中的Function(priceTier)
相同)
MergeOption
在执行查询时应设置为其他而不是NoTracking
。否则,EF将无法确保在查询结果集中多次出现的对象仅实现一次,例如Product
或ChildProduct
:
不需要的结果: PriceTier 1和2具有相同的父母,但父母已多次实现 - 每个PriceTier一次。
理想的结果:
将MergeOption
设置为NoTracking
以外的任何内容即可获得以下结果:
答案 1 :(得分: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};