实体框架4:使用自我跟踪实体的过滤器进行预先加载(包括)

时间:2010-08-29 16:12:02

标签: .net sql-server linq ado.net entity-framework-4

我有一个解决方案,我使用RTM模板创建了自我跟踪实体。我已经拆分了2个项目之间的实体和上下文,以便我可以重用类型定义,因为我打算通过WCF运行客户端/服务器。

我的一个服务方法需要返回带有“ProductSku”子对象的“Product”对象的图形,而这些对象又具有“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

......但这也没什么区别。

显然,我必须做错事。任何人都可以了解那些东西是什么,因为我已经在这里玩了几个小时现在绕圈子了!

4 个答案:

答案 0 :(得分:1)

编辑:

怎么样:

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

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

还要注意条件只过滤产品。它不会过滤由Include加载的数据 - 您将获得至少一个具有财务期ID为244的价格历史的sku的所有产品,但这些产品将加载所有skus和价格历史记录。 EF目前不支持对include进行过滤。如果您还需要过滤关系,则必须执行单独的查询才能获得它们。

答案 1 :(得分:1)

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

查看Linq filter collection with EF

答案 2 :(得分:0)

包含Include并不能保证拥有热切的加载,并且由于以下原因可能会被忽略。在这个帖子中有更好的解释。 您可以手动选择要加载的表格,例如

In [38]: Foo.mutate is Foo.mutate
Out[38]: True

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采用的参数是以点分隔的导航路径 必须可从该类型的实例导航的属性 在最外面的操作返回

答案 3 :(得分:-1)

未启用自跟踪实体来执行延迟加载。 这就是为什么集合在默认实体生成时不是空的而不是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;

希望有所帮助

马修