实体框架预加载过滤器

发布于 2024-11-01 22:27:57 字数 673 浏览 0 评论 0原文

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

1)ProductsChildProducts,其中有PriceTiers
2) 我想获取 Category 的所有 Products,其 ID 为 1 且 Display = true .
3) 我想包含所有具有 Display = true 的 ChildProducts
4) 然后包含 IsActive = true 的 PriceTiers

据我所知,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)))

有什么建议吗?

I have a simple query I want to do like this:

1) Products have ChildProducts which have PriceTiers
2) I want to get all the Products that have a Category with a ID of 1 and Display = true.
3) I want to then include all the ChildProducts that have Display = true.
4) And then include the PriceTiers that have IsActive = true.

From what I have read, EF does not support Eager Loading with filters, so the following will not work:

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)))

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˇ宁静的妩媚 2024-11-08 22:27:57

从下往上开始,意思是,对 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# 中的 Function(priceTier) 与 VB.NET 中的 Function(priceTier) 相同)

MergeOption 理想情况下应设置为其他执行查询时NoTracking。否则,EF 将无法确保在查询结果集中多次出现的对象仅实现一次,例如 ProductChildProduct

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

  • 产品1
    • 子产品 1
      • 价格等级 1
  • 产品 1
    • 子产品 1
      • 价格等级 2

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

  • 产品 1
    • 子产品 1
      • 价格等级 1
      • 价格等级 2

Start from the bottom up, meaning, apply filter on the PriceTier object and its parents, and include its parents (C# sorry, but hopefully you get the point):

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

(Note: priceTier => in C# is the same as Function(priceTier) in VB.NET)

MergeOption should ideally be set to something other than NoTracking when executing the query. Otherwise, EF will not ensure that an object that appears multiple times in the result set of the query is only materialized once, such as a Product or ChildProduct:

Unwanted results:
PriceTier 1 and 2 have the same parents, but the parents have been materialized multiple times - once for each PriceTier.

  • Product 1
    • ChildProduct 1
      • PriceTier 1
  • Product 1
    • ChildProduct 1
      • PriceTier 2

Ideal results:
Set MergeOption to anything other than NoTracking to get these results:

  • Product 1
    • ChildProduct 1
      • PriceTier 1
      • PriceTier 2
眼中杀气 2024-11-08 22:27:57

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

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

here is a solution that will give your 'rows' to match your request by using left joins instead of eager loading, and including parent rows where no child rows exist for the filters

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};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文