Ответ 1
В конце концов, для меня EF все еще не хватает зрелости и функций, необходимых для выступления в большом мире. Поэтому я отказался от него в пользу NHibernate, который генерирует просто красивый и оптимизированный SQL.
Может ли кто-нибудь объяснить, почему объединение сущностью, а не id генерирует какой-то действительно уродливый sql, когда на самом деле концептуально это делает то, что вы считаете одним и тем же? например.
По id
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]
)
Это выглядит довольно неэффективно для меня, заставляя вас идти по маршруту id. Почему он делает левое соединение дважды, неважно, раз?
В конце концов, для меня EF все еще не хватает зрелости и функций, необходимых для выступления в большом мире. Поэтому я отказался от него в пользу NHibernate, который генерирует просто красивый и оптимизированный SQL.
Я не могу сказать, что находится в умах или в коде команды ADO.NET. Тем не менее, я вижу две возможные проблемы:
Id
в базовой таблице в ContractAddresses
или, возможно, только в модели сущности, не может быть определено как первичный ключ. Я несколько сомневаюсь, что это проблема, но стоит дважды проверить.equals
может не иметь хорошего способа сравнить равенство между двумя объектами в соединении. В быстром веб-поиске я не нашел то, что использует equals
для сравнения, но это руководство MSDN заставляет меня думать, что задействованы методы equals
и GetHashCode
(даже если составные клавиши не задействованы). Если вы используете только унаследованный метод object.Equals
по умолчанию, поставщик Linq должен каким-то образом определить ссылочное равенство, которое, как я полагаю, может привести к некоторым странным результатам.Мне нравится решение @Craig Stuntz в его комментарии. Кроме того, вы можете захотеть получить план выполнения для более длинного запроса, чтобы увидеть, действительно ли это так плохо, как выглядит; оптимизатор запросов может сделать лучшую работу, чем указывает код.