В чем разница между использованием Join in Linq и синтаксиса pre ANSI join "Olde Style"? - PullRequest
6 голосов
/ 06 августа 2009

Этот вопрос вытекает из вопроса Вчера я спрашивал о том, почему использование запроса на объединение в моих сущностях приводит к ужасно сложному SQL. Казалось, что выполнение запроса выглядит так:

        var query = from ev in genesisContext.Events
                    join pe in genesisContext.People_Event_Link
                    on ev equals pe.Event
                    where pe.P_ID == key
                    select ev;

Произвел ужасный SQL, который потребовал 18 секунд для запуска в базе данных, в то время как объединение сущностей с помощью предложения where (что-то вроде синтаксиса pre-ANSI SQL) заняло меньше секунды и дало тот же результат

        var query = from pe in genesisContext.People_Event_Link
                    from ev in genesisContext.Events
                    where pe.P_ID == key && pe.Event == ev
                    select ev;

Я гуглил повсюду, но до сих пор не понимаю, почему второй генерирует SQL, отличный от первого. Может кто-нибудь, пожалуйста, объясните мне разницу? Когда следует использовать ключевое слово join


Это SQL, который был создан, когда я использовал Join в своем запросе, и для его выполнения потребовалось 18 секунд:

SELECT 
1 AS [C1], 
[Extent1].[E_ID] AS [E_ID], 
[Extent1].[E_START_DATE] AS [E_START_DATE], 
[Extent1].[E_END_DATE] AS [E_END_DATE], 
[Extent1].[E_COMMENTS] AS [E_COMMENTS], 
[Extent1].[E_DATE_ADDED] AS [E_DATE_ADDED], 
[Extent1].[E_RECORDED_BY] AS [E_RECORDED_BY], 
[Extent1].[E_DATE_UPDATED] AS [E_DATE_UPDATED], 
[Extent1].[E_UPDATED_BY] AS [E_UPDATED_BY], 
[Extent1].[ET_ID] AS [ET_ID], 
[Extent1].[L_ID] AS [L_ID]
FROM  [dbo].[Events] AS [Extent1]
INNER JOIN [dbo].[People_Event_Link] AS [Extent2] ON  EXISTS (SELECT 
    1 AS [C1]
    FROM    ( SELECT 1 AS X ) AS [SingleRowTable1]
    LEFT OUTER JOIN  (SELECT 
            [Extent3].[E_ID] AS [E_ID]
        FROM [dbo].[Events] AS [Extent3]
        WHERE [Extent2].[E_ID] = [Extent3].[E_ID] ) AS [Project1] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent4].[E_ID] AS [E_ID]
        FROM [dbo].[Events] AS [Extent4]
        WHERE [Extent2].[E_ID] = [Extent4].[E_ID] ) AS [Project2] ON 1 = 1
    WHERE ([Extent1].[E_ID] = [Project1].[E_ID]) OR (([Extent1].[E_ID] IS NULL) AND ([Project2].[E_ID] IS NULL))
)
WHERE [Extent2].[P_ID] = 291

Это SQL, который был создан с использованием синтаксиса стиля ANSI (и он довольно близок к тому, что я написал бы, если бы писал сам SQL):

SELECT * FROM Events AS E INNER JOIN People_Event_Link AS PE ON E.E_ID=PE.E_ID INNER JOIN PEOPLE AS P ON P.P_ID=PE.P_ID
WHERE P.P_ID = 291

1 Ответ

4 голосов
/ 06 августа 2009

Ни один из приведенных выше запросов не является полностью «правильным». В EF, как правило, правильно использовать свойства отношений вместо любого из вышеперечисленных. Например, если у вас есть объект Person с отношением один-ко-многим к PhoneNumbers в свойстве Person.PhoneNumbers, вы можете написать:

var q = from p in Context.Person
        from pn in p.PhoneNumbers
        select pn;

EF создаст объединение для вас.

С точки зрения приведенного выше вопроса причина, по которой генерируемый SQL отличается, заключается в том, что деревья выражений отличаются, даже если они дают эквивалентные результаты. Деревья выражений отображаются на SQL, и вы, конечно, знаете, что вы можете писать разные SQL, которые дают одинаковые результаты, но с разной производительностью. Отображение предназначено для создания достойного SQL, когда вы пишете «обычный» EF-запрос.

Но отображение не такое умное, чтобы брать очень нестандартный запрос и оптимизировать его. В своем первом запросе вы утверждаете, что объекты должны быть эквивалентны. Во втором случае вы утверждаете, что свойство ID должно быть эквивалентным. В приведенном выше примере запроса сказано: «просто получите детали для этой записи». EF предназначен для работы, как показано в принципе, но также хорошо справляется со скалярной эквивалентностью.

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