【问题标题】:LINQ Query Using Navigation Properties Generates Multiple SELECT Statements使用导航属性的 LINQ 查询生成多个 SELECT 语句
【发布时间】:2013-08-24 03:30:50
【问题描述】:

我有一个 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 记录后,域类将包含如下便利属性:

public IQueryable<SpecialOfferProduct> SpecialProducts
    {
        get
        {
            return SalesOrderDetails.Where(sod => sod.OrderQty > 3)
                                    .Select(s => s.SpecialOfferProduct)
                                    .AsQueryable();
        }
    }

此语句产生多个 SELECT 语句:一个对应于 SpecialOfferProduct 中的每条记录。我的问题是:为什么导航属性不生成单个 SELECT 语句?这是一个巨大的性能问题,因为它会产生很多不必要的喋喋不休。我可以使用 LINQ SQL 语法,但这只是在使用存储库进行原始查询时。在这种情况下,我有一个 SalesOrderHeader 对象的实例,并且无权访问类中的 Context 或 Repository。有没有办法强制它使用 JOIN 创建单个 SELECT 语句?

如果没有办法做到这一点,我正在考虑在我的存储库中创建一个额外的方法来填充这些属性。问题是我有两个步骤:1 检索 SalesOrderHeader 对象,然后另一个使用适当的 LINQ 语句填充其他属性,这将强制 JOIN 语法。

【问题讨论】:

  • 您已将延迟加载设置为 true。将其设置为 false 或使用Include 方法急切加载导航属性实体。

标签: c# sql linq entity-framework linq-to-entities


【解决方案1】:

正如评论中所说,您需要Include 方法:

SalesOrderHeaders.Include(s => s.SalesOrderDetails
                                .Select(d => d.SpecialOfferProduct))
                 .Where(s => s.SalesOrderID == 43659)
                 .Single().SalesOrderDetails

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

但是请注意,您不能使用类似的语法

.Include(s => s.SalesOrderDetails.Where(sod => sod.OrderQty > 3)
               .Select(d => d.SpecialOfferProduct))

这似乎会部分填充SalesOrderDetails。 EF 团队收到了一些变更请求来实现这一点,但到目前为止,这还没有完成。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多