LINQ to Entities, присоединяясь к экземпляру, а не к id, генерирует неприятный SQL - PullRequest
14 голосов
/ 11 мая 2011

Может ли кто-нибудь объяснить, почему соединение по сущности, а не по идентификатору генерирует действительно ужасный sql, хотя на самом деле концептуально он делает то, что, как вы думаете, было тем же самым?например,

По идентификатору

from companyDirector in CompanyDirectors
join contactAddress in ContactAddresses
  on companyDirector.ContactAddress.Id equals contactAddress.Id
select new {companyDirector, contactAddress}

Создает

FROM  [COMPANY] AS [Extent1]
    INNER JOIN [ADDRESS] AS [Extent2] ON [Extent1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID]

По экземпляру

from companyDirector in CompanyDirectors
join contactAddress in ContactAddresses
  on companyDirector.ContactAddress equals contactAddress
select new {companyDirector, contactAddress}

создает

FROM  [COMPANY] AS [Extent1]
INNER JOIN [ADDRESS] AS [Extent2] ON  EXISTS (SELECT 
    1 AS [C1]
    FROM    ( SELECT 1 AS X ) AS [SingleRowTable1]
    LEFT OUTER JOIN  (SELECT 
        [Extent3].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
        FROM [ADDRESS] AS [Extent3]
        WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent3].[CONTACT_ADDRESS_ID] ) AS [Project1] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent4].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
        FROM [ADDRESS] AS [Extent4]
        WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent4].[CONTACT_ADDRESS_ID] ) AS [Project2] ON 1 = 1
    WHERE [Project1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID]
)

Этовыглядит довольно неэффективно для меня, заставляя вас идти по маршруту.Почему он делает левое соединение дважды, не говоря уже об одном ??

Ответы [ 2 ]

1 голос
/ 19 мая 2011

Я не могу сказать, что умы или код команды ADO.NET. Тем не менее, я вижу две возможные проблемы:

  1. Возможно, поле Id в базовой таблице в ContractAddresses или, возможно, просто в модели объекта, не может быть определено как первичный ключ. Я немного сомневаюсь, что это проблема, но стоит перепроверить.
  2. Ключевое слово equals может не совсем реально сравнить равенство между двумя объектами в соединении. В быстром веб-поиске я не нашел точно , что equals использует для сравнения, но этот MSDN с инструкциями заставляет меня поверить, что Equals и GetHashCode методы задействованы (даже если составные ключи не задействованы). Если вы просто используете унаследованный по умолчанию метод object.Equals, провайдер Linq должен каким-то образом выяснить равенство ссылок, что, как мне кажется, может привести к некоторым странным результатам.

Мне нравится решение @Craig Stuntz в его комментарии. Кроме того, вы можете получить план выполнения для более длинного запроса, чтобы увидеть, действительно ли он так плох, как кажется; Оптимизатор запросов мог бы работать лучше, чем показывал бы код.

0 голосов
/ 21 июня 2012

В конце концов, для меня EF все еще не хватает зрелости и возможностей, необходимых для работы в большом мире.Поэтому я отказался от него в пользу NHibernate, который генерирует просто красивый и оптимизированный SQL.

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