C# 使用导航属性的LINQ查询生成多个SELECT语句

C# 使用导航属性的LINQ查询生成多个SELECT语句,c#,sql,linq,entity-framework,linq-to-entities,C#,Sql,Linq,Entity Framework,Linq To Entities,我有一个POCO域实体类,其中包含导航到相关记录的方便方法。我正在使用AdventureWorks2008R2数据库来演示我试图实现的目标。所有这些查询都可以在LINQPad中运行,以观察生成的SQL语句 SalesOrderHeaders.Where(s=>s.SalesOrderID==43659) .Single().SalesOrderDetails 此语句生成2条SQL语句。一个用于SalesOrderHeader记录,另一个用于检索SalesOrderDetails。现在考虑这个导

我有一个POCO域实体类,其中包含导航到相关记录的方便方法。我正在使用AdventureWorks2008R2数据库来演示我试图实现的目标。所有这些查询都可以在LINQPad中运行,以观察生成的SQL语句

SalesOrderHeaders.Where(s=>s.SalesOrderID==43659)
.Single().SalesOrderDetails
此语句生成2条SQL语句。一个用于SalesOrderHeader记录,另一个用于检索SalesOrderDetails。现在考虑这个导航到一个附加的相关表:

SalesOrderHeaders.Where(s=>s.SalesOrderID==43659)
.Single().SalesOrderDetails.Select(s=>s.SpecialOfferProduct)
检索单个SalesOrderHeader记录后,域类将包含如下便利属性:

公共可查询特殊产品
{
得到
{
返回SalesOrderDetails.Where(sod=>sod.OrderQty>3)
.选择(s=>s.SpecialOfferProduct)
.AsQueryable();
}
}
此语句生成多个SELECT语句:SpecialOfferProduct中的每条记录一个SELECT语句。我的问题是:为什么导航属性不生成一个SELECT语句?这是一个巨大的性能问题,因为它会产生大量不必要的干扰。我可以使用LINQSQL语法,但这仅限于使用存储库进行原始查询时。在本例中,我有一个SalesOrderHeader对象的实例,但无权访问该类中的上下文或存储库。有没有办法强迫它使用联接创建一个SELECT语句


如果没有办法,我想在我的存储库中创建一个额外的方法来填充这些属性。问题是,我有两个步骤:1检索SalesOrderHeader对象,然后使用适当的LINQ语句填充附加属性,这将强制执行联接语法。

如注释中所述,您需要该方法:

这将连接所需的数据(SQL)并填充导航属性

但是,请注意,不能使用如下语法

.Include(s => s.SalesOrderDetails.Where(sod => sod.OrderQty > 3)
               .Select(d => d.SpecialOfferProduct))
这似乎会部分填充
SalesOrderDetails
。有人向EF团队提出变更请求以实现这一点,但到目前为止,还没有这样做


另一个注意事项是,将
SpecialProducts
返回为
IQueryable
是没有用的,因为对集合的后续查询无论如何都不会转换为SQL。首先,您只能在内存语句中访问属性,而不能在linq to enitites查询中访问属性(EF无法将属性转换为SQL)。

您的延迟加载设置为true。将其设置为false或使用
Include
方法急切地加载导航属性实体。
.Include(s => s.SalesOrderDetails.Where(sod => sod.OrderQty > 3)
               .Select(d => d.SpecialOfferProduct))