实体框架 4:使用自跟踪实体通过过滤器进行预加载(包含)

发布于 2024-09-17 07:01:02 字数 1183 浏览 5 评论 0原文

我有一个解决方案,我使用 RTM 模板创建了自我跟踪实体。我已将实体和上下文拆分为两个项目,以便在计划通过 WCF 运行客户端/服务器时可以重用类型定义。

我的服务方法之一需要返回“Product”对象的图形,其中子对象为“ProductSku”,而这些对象又具有“ProductPrice”的子对象。选择标准将位于“Product”对象的“Name”属性和“ProductPriceObject”的“FinancialPeriodID”属性上。目前,我没有在搜索中包含该名称,但在返回图表时遇到问题。

如果我只是执行以下查询(请注意,此语法取自 LinqPad 而不是实际的应用程序代码)...

from product in Products.Include("Skus.PriceHistory")
select product

...那么我就能够检索我需要的项目的完整对象图,当然在此点没有过滤器。

相反,如果我按如下方式引入过滤器...

from product in Products.Include("Skus.PriceHistory")
join sku in ProductSkus on product.ID equals sku.ProductID
join price in ProductPrices on sku.ID equals price.ProductSkuID
where price.FinancialPeriodID == 244
select product

...我期望返回的是“Product”对象,子“ProductSku”对象(位于“Product”的“Skus”集合中)及其“ProductPrice”对象(位于“ProductSku”的“PriceHistory”集合中) - 但我只取回“Product”对象,“Skus”集合为空。

我也尝试将查询编码为……

from product in Products.Include("Skus.PriceHistory")
from sku in product.Skus
from price in sku.PriceHistory
where price.FinancialPeriodID == 244
select product

但这也没有什么区别。

显然,我一定做错了什么。任何人都可以阐明那是什么东西,因为我已经在这几个小时了,现在一直在兜圈子!

I have a solution where I have created self tracking entities using the RTM templates. I have split the entities and context between 2 projects so that I can reuse the type definitions as I plan to run client/server via WCF.

One of my service methods is required to return a graph of "Product" objects with child objects of "ProductSku" and these in turn have child objects of "ProductPrice". The selection criteria will be on the "Name" property of the "Product" object, and the "FinancialPeriodID" property of the "ProductPriceObject". For now, I am not including the name in the search, but I am having problems bringing back the graph.

If I simply perform the following query (note, this syntax is taken from LinqPad rather than the actual application code)...

from product in Products.Include("Skus.PriceHistory")
select product

... then I am able to retrieve the full object graph for the items that I require, of course at this point there is no filter.

If instead, I introduce the filter as follows...

from product in Products.Include("Skus.PriceHistory")
join sku in ProductSkus on product.ID equals sku.ProductID
join price in ProductPrices on sku.ID equals price.ProductSkuID
where price.FinancialPeriodID == 244
select product

... what I am expecting to get back is the "Product" objects, the child "ProductSku" objects (which are in the "Skus" collection of the "Product") and their "ProductPrice" objects (which are in the "PriceHistory" collection of the "ProductSku") - but I only get back the "Product" objects, the "Skus" collection is empty.

I have also tried coding the query as ...

from product in Products.Include("Skus.PriceHistory")
from sku in product.Skus
from price in sku.PriceHistory
where price.FinancialPeriodID == 244
select product

... but this makes no difference either.

Clearly, I must be doing something wrong. Can anybody shed any light on what that something is as I have been at this for some hours now going around in circles!

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

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

发布评论

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

评论(4

很酷不放纵 2024-09-24 07:01:02

也许投影可以做到这一点?

查看使用 EF 的 Linq 过滤器集合

Maybe projection can do this trick?

Take a look at Linq filter collection with EF

乖不如嘢 2024-09-24 07:01:02

编辑:

怎么样:

from product in Products.Include("Skus.PriceHistory")
where product.Skus.Any(s => s.PriceHistory.Any(p => p.FinancialPeriodID == 244))
select product

Include 已经执行了所有必要的任务来填充导航属性,因此不需要附加的 where 条件连接。更重要的是,任何手动连接或投影都会改变查询的形状,并且 Include 将不会被使用。

另请注意,where 条件仅过滤产品。它不会过滤“包含”加载的数据 - 您将获得至少有一个 sku 具有财务周期 id 244 的价格历史记录的所有产品,但这些产品将加载所有 sku 和价格历史记录。 EF 目前不支持对包含进行过滤。如果您还需要过滤关系,则必须执行单独的查询来获取它们。

Edit:

What about:

from product in Products.Include("Skus.PriceHistory")
where product.Skus.Any(s => s.PriceHistory.Any(p => p.FinancialPeriodID == 244))
select product

Include already performs all necessary tasks to fill navigation properties so additional joins for where condition are not needed. What is even more important any manual join or projection will change the shape of the query and Include will not be used.

Also beware that where condition filters only products. It will not filter data loaded by Include - you will get all products with at least one sku having price history with financial period id 244 but those products will have all skus and price histories loaded. EF currently does not support filtering on include. If you need filtered relations as well you have to execute separate queries to get them.

冷情妓 2024-09-24 07:01:02

拥有 Include 并不能保证立即加载,并且由于以下原因可能会被默默地忽略。这个线程中有更好的解释。
您可以手动选择要加载的表,例如

var result = from product in Products.Include("Skus.PriceHistory")
from sku in product.Skus
from price in sku.PriceHistory
where price.FinancialPeriodID == 244
select new { p=product, pricehistory = product.Skus.PriceHistory};
var products = results.select(pph => pph.product);

https://social.msdn.microsoft.com/Forums/en-US/76bf1f22-7674-4e1e-85d3-68d29404e8db/include-is-ignored -in-a-subquery?forum=adodotnetentityframework

  • 包含仅适用于查询结果中的项目:
    投影到查询中最外层的操作。
  • 结果的类型必须是实体类型。
  • 查询不能包含更改类型的操作
    Include 和最外层操作之间的结果(即 GroupBy()
    或更改结果类型的 Select() 操作)
  • Include 所采用的参数是点分隔的导航路径
    必须可从该类型的实例导航的属性
    在最外层操作返回

Having Include is not a guarantee to have eager loading and it could be ignored silently because of the following reason. It is better explained in this thread.
You can manually select the table you like to load e.g.

var result = from product in Products.Include("Skus.PriceHistory")
from sku in product.Skus
from price in sku.PriceHistory
where price.FinancialPeriodID == 244
select new { p=product, pricehistory = product.Skus.PriceHistory};
var products = results.select(pph => pph.product);

https://social.msdn.microsoft.com/Forums/en-US/76bf1f22-7674-4e1e-85d3-68d29404e8db/include-is-ignored-in-a-subquery?forum=adodotnetentityframework

  • Include only applies to items in the query results: objects that are
    projected at the outermost operation in the query.
  • The type of the results has to be an entity type.
  • The query cannot contain operations that change the type of the
    result between Include and the outermost operation (i.e. a GroupBy()
    or a Select() operation that changes the result type)
  • The parameter taken by Include is a dot-delimited path of navigation
    properties that have to be navigable from an instance of the type
    returned at the outermost operation
堇年纸鸢 2024-09-24 07:01:02

自跟踪实体无法执行延迟加载。
这就是为什么默认实体生成时集合不为空,而 STE 时集合不为空。事实上,如果您在查询中使用相关实体,您的 Include 永远不会加载它们。
现在您的 L2E 查询不正确。我认为你想做这样的事情:

from p in 
   (from product in Products
    select new 
    { 
       Product = product, 
       Skus = 
          from sku in product.Skus
          select new 
          { 
             Sku = sku, 
             Prices = 
                from price in sku.Prices
                where price.FinancialPeriodID == 244            
                select price
          }
    }).AsEnumerable()
select p.Product;

希望对

马蒂厄有帮助

Self-tracking entities are not enabled to perform lazy loading.
That's why collection are not empty with default entity generation and not with STE. In fact your Include never loads related entities if you use them on the query.
Now your L2E query is not correct. I think that you want to do something like this:

from p in 
   (from product in Products
    select new 
    { 
       Product = product, 
       Skus = 
          from sku in product.Skus
          select new 
          { 
             Sku = sku, 
             Prices = 
                from price in sku.Prices
                where price.FinancialPeriodID == 244            
                select price
          }
    }).AsEnumerable()
select p.Product;

Hope that helps

Matthieu

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