代码之家  ›  专栏  ›  技术社区  ›  e36M3

这两个LINQ查询有什么区别?

  •  3
  • e36M3  · 技术社区  · 15 年前

    查看这个分析器,我发现了一些不同之处。第二个查询使用 包括 将实际返回与第二个表countrycode相关的数据。这部分对我来说是有意义的。但是,我不理解为什么这个查询有两个连接。首先,它在countrycodes和countycodetypes(在外键上)之间执行常规的内部联接,我认为这足以返回 包括 要求。但是,它会执行另一个外部联接。为什么?

    var query = from codes in base.context.CountryCodes
                join codeTypes in base.context.CountryCodeTypes
                on codes.CountryCodeTypeId equals codeTypes.CountryCodeTypeId
                where codeTypes.CountryCodeTypeName == countryCodeType
                select codes;
    
    var query = from codes in base.context.CountryCodes.Include("CountryCodeType")
                where codes.CountryCodeType.CountryCodeTypeName == countryCodeType
                select codes;
    

    结果SQL:

     FROM   [dbo].[CountryCode] AS [Extent1]
     INNER JOIN [dbo].[CountryCodeType] AS [Extent2] ON [Extent1].[CountryCodeTypeId] = [Extent2].[CountryCodeTypeId]
     LEFT OUTER JOIN [dbo].[CountryCodeType] AS [Extent3] ON [Extent1].[CountryCodeTypeId] = [Extent3].[CountryCodeTypeId]
     WHERE [Extent2].[CountryCodeTypeName] = @p__linq__0
    

    另外,公平地说,我应该使用.仅当我实际需要在结果中填充外键表中的数据时才包含,否则使用联接吗?换句话说,我不应该使用.include作为联接的方法,因为导航属性知道如何基于键为我联接实体。

    2 回复  |  直到 15 年前
        1
  •  4
  •   Kirk Broadhurst    15 年前

    这只是实体框架生成的SQL的本质。

    内部连接的存在是因为 where 语句。

    where codes.CountryCodeType.CountryCodeTypeName == countryCodeType
    

    正如您正确指出的,EF可以解决这一问题的唯一方法是执行内部联接。注意到内部联接实际上返回了满足 Include() .

    但是,外部联接仍然被执行,这仅仅是因为EF看到 包含() 并将其解析为需要联接。考虑一下你没有 在哪里? 你需要一个外部连接,对吗?嗯,ef不够聪明,无法确定在这种情况下不需要外部连接;它看到一个 包含() 然后生成相关的外部连接,以确保满足数据需求。换句话说,它并没有考虑查询的其余部分来确定是否需要联接——它只是不考虑。

    关于 包含() 运算符,只有在希望将这些相关对象检索回应用程序时才使用它。此查询不需要。在这种情况下,最简单的查询是

    var query = from codes in base.context.CountryCodes
                where codes.CountryCodeType.CountryCodeTypeName == countryCodeType
                select codes;
    
        2
  •  2
  •   StriplingWarrior    15 年前

    左外部联接是由于 codes.CountryCodeType.CountryCodeTypeName == countryCodeType ,而内部联接恰好允许它在最终结果中包含CountryCodeType表中的字段。

    如果结果中不需要外键表中的数据,则不需要使用include 加入。如果不使用“include”,则只使用左外部联接,而不使用内部联接。

    我猜想这个框架还不够聪明,不能意识到它已经在那个表上完成了一个连接,并且可以重用那里的信息。希望SQL Server足够聪明,能够理解这一点,并使用一个避免重复这一工作的执行计划。