В чем разница между этими двумя запросами LINQ? - PullRequest
3 голосов
/ 15 октября 2010

Глядя на профилировщик, я вижу несколько отличий. Второй запрос, который использует include , фактически возвращает данные из связанной с CountryCodes вторичной таблицы. Эта часть имеет смысл для меня. Я, однако, не понимаю, почему этот запрос имеет два соединения. Сначала выполняется регулярное внутреннее соединение между 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 только тогда, когда мне действительно нужны данные в таблице внешнего ключа для заполнения в моем результате, в противном случае используйте соединение? Другими словами, я не должен использовать .Include в качестве средства для объединения, потому что навигационные свойства знают, как соединять сущности для меня на основе ключей.

Ответы [ 2 ]

4 голосов
/ 15 октября 2010

Это просто природа сгенерированного SQL Entity Framework.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ существует из-за вашего оператора where.

where codes.CountryCodeType.CountryCodeTypeName == countryCodeType

Единственный способ, с помощью которого EF может решить эту проблему, - это выполнить ВНУТРЕННЕЕ СОЕДИНЕНИЕ, как вы правильно указали. Вы также правильно заметили, что ВНУТРЕННЕЕ СОЕДИНЕНИЕ действительно возвращает все данные, необходимые для удовлетворения Include().

Однако OUTER JOIN все еще выполняется, просто потому что EF видит Include() и анализирует его как требующее объединения. Рассмотрим случай, когда у вас нет предложения where - тогда вам понадобится OUTER JOIN, верно? Ну, EF недостаточно умен, чтобы определить, что в этом случае OUTER JOIN не требуется; он видит Include() и затем генерирует соответствующее ВНЕШНЕЕ СОЕДИНЕНИЕ, чтобы гарантировать, что требования к данным будут удовлетворены. Другими словами, он не учитывает остальную часть вашего запроса, чтобы определить, требуется ли объединение - он просто делает это независимо.

Что касается оператора Include(), вы можете использовать его только тогда, когда хотите извлечь эти связанные объекты обратно в ваше приложение. Это не требуется для этого запроса. Самый простой запрос в этом случае будет

var query = from codes in base.context.CountryCodes
            where codes.CountryCodeType.CountryCodeTypeName == countryCodeType
            select codes;
2 голосов
/ 15 октября 2010

Левое внешнее объединение происходит в результате codes.CountryCodeType.CountryCodeTypeName == countryCodeType, тогда как внутреннее объединение позволяет ему включать поля из таблицы CountryCodeType в окончательные результаты.

Если вам не нужны данные из таблицы внешнего ключа в вашем результате, вам не нужно использовать Включить или Присоединиться.Если бы вы не использовали «Включить», оно использовало бы только левое внешнее соединение, а не внутреннее соединение.

Я предполагаю, что фреймворк просто недостаточно умен, чтобы понять, что он уже сделан.присоединиться к этой таблице, и можете использовать информацию там.Надеюсь, SQL Server достаточно умен, чтобы понять это и использовать план выполнения, который позволяет избежать дублирования этих усилий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...