2010-10-14 98 views
3

看着分析器,我看到了一些差異。使用的第二個查詢包括實際上將返回與輔助表CountryCodes相關的數據。這部分對我來說很有意義。但我不明白爲什麼這個查詢有兩個連接。首先它在CountryCodes和CountyCodeTypes(在外鍵上)之間進行常規的內連接,我認爲這足以返回包括所需的所有內容。然而,它然後做另一個外部聯接。爲什麼?這兩個LINQ查詢有什麼區別?

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

這不是你的問題的SQL是否由第一或第二的LINQ查詢生成非常清楚... – 2010-10-15 00:12:59

回答

4

這只是實體框架生成的SQL的本質。

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

where codes.CountryCodeType.CountryCodeTypeName == countryCodeType 

EF可以解決此問題的唯一方法是執行INNER JOIN,正如您正確指出的那樣。您也注意到INNER JOIN確實返回了滿足Include()所需的所有數據。

但是,外部連接仍然執行,只是因爲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; 
+0

謝謝柯克。那麼說這麼說是公平的,那麼你在沒有連接的情況下提出的查詢就等於我用JOIN編寫的查詢。但是,您的查詢只是利用從數據模型推斷的導航屬性?我也明白你的意思是把'Include()'翻譯成一個自動的OUTER JOIN。然而有一點想到。在兩個表之間實際上存在外鍵約束的情況下,INNER JOIN不會足夠嗎? – e36M3 2010-10-15 00:36:48

+0

1 /您可以使用數據模型中描述的導航屬性執行連接 - 我相信這是EF的一箇中心特性。 2 /如果你沒有做'where',那就沒有INNER JOIN。如果你想用'Include'檢索相關的對象,如果EF使用INNER JOIN,你只能檢索那些有相關對象的對象。 OUTER JOIN確保您檢索具有相關對象的那些,以及不包含那些(OUTER JOIN爲空)的那些對象。 – 2010-10-15 00:54:38

2

由於codes.CountryCodeType.CountryCodeTypeName == countryCodeType的結果,左外連接發生,而內連接恰好允許它在最終結果中包含來自CountryCodeType表的字段。

如果在結果中不需要外鍵表中的數據,則不需要使用Include Join。如果你沒有使用「包含」,它只會使用左外連接,而不是內連接。

我猜這個框架根本不夠聰明,意識到它已經在該表上做了一個連接,並且可以重用那裏的信息。希望SQL Server足夠聰明,可以接受這一點,並使用執行計劃來避免重複工作。

+0

難道我需要爲我做的地方加入條件雖然? – e36M3 2010-10-15 00:09:08

+0

不是。該框架計算出您正在引用一個相關的表並在SQL中創建必要的連接,這只是基於屬性訪問。 – StriplingWarrior 2010-10-15 15:16:59

+0

我剛纔意識到我有內連接和外連接向後。柯克的回答更爲正確。 – StriplingWarrior 2010-10-15 15:18:26