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

时间:2010-10-14 23:53:01

标签: c# asp.net linq entity-framework linq-to-entities

查看分析器,我看到了一些差异。使用 include 的第二个查询实际上将返回与辅助表CountryCodes相关的数据。这部分对我有意义。但是我不明白为什么这个查询有两个连接。首先,它在CountryCodes和CountyCodeTypes(在外键上)之间进行常规内连接,我认为这足以返回 include 所需的所有内容。然而,它然后做另一个外连接。为什么呢?

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,否则使用连接?换句话说,我不应该使用.Include作为连接的手段,因为导航属性知道如何根据键为我加入实体。

2 个答案:

答案 0 :(得分:4)

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

INNER JOIN因您的where声明而存在。

where codes.CountryCodeType.CountryCodeTypeName == countryCodeType

EF可以解决此问题的唯一方法是执行INNER JOIN,正如您正确指出的那样。你也注意到INNER JOIN确实返回了满足Include()所需的所有数据。

然而,OUTER JOIN仍然执行,只是因为EF看到Include()并将其解析为需要加入。考虑一下你没有where子句的情况 - 你需要一个OUTER JOIN,对吧?在这种情况下,EF不够聪明,无法确定是否需要OUTER JOIN;它会看到Include(),然后生成相关的OUTER JOIN,以确保满足数据要求。换句话说,它没有考虑你的查询的其余部分来确定是否需要连接 - 它只是无论如何。

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

var query = from codes in base.context.CountryCodes
            where codes.CountryCodeType.CountryCodeTypeName == countryCodeType
            select codes;

答案 1 :(得分:2)

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

如果您不需要结果中外键表中的数据,则无需使用Include Join。如果你没有使用“Include”,它只会使用左外连接,而不是内连接。

我猜这个框架根本不够聪明,无法意识到它已经在该表上完成了连接,并且可以在那里重用信息。希望SQL Server足够聪明,可以接受并使用执行计划,避免重复这种努力。