2009-08-06 14 views
6

Questa domanda segue da un question Ho chiesto ieri sul motivo per cui l'utilizzo della query di join sulle mie entità ha prodotto SQL terribilmente complicato. Sembrava che l'esecuzione di una query come questa:Qual è la differenza tra l'utilizzo di Join in Linq e la sintassi di join ANSI pre-ANSI "Olde Style"?

 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; 

Prodotto SQL orribile che ha preso 18 secondi per l'esecuzione sul database, mentre unendo i soggetti attraverso una clausola in cui (un po 'come ANSI pre-sintassi SQL) ha richiesto meno di un secondo per eseguire e prodotto lo stesso risultato

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

googled tutto, ma ancora non capisco perché il secondo è produce SQL diverso dal primo. Qualcuno può spiegarmi la differenza? Quando devo usare la parola join


Questa è la SQL che è stato prodotto quando ho usato unirvi alla mia interrogazione e ha preso 18 secondi per eseguire:

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 

Questa è la SQL che è stata la produzione utilizzando la sintassi ANSI stile (ed è abbastanza vicino a quello che avrei scritto se stessi scrivendo il codice SQL me):

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 
+0

Ottima domanda. – tomfanning

+0

Che DB stai usando? Come appare il codice SQL? – AnthonyWJones

risposta

4

Nessuna delle query di cui sopra è del tutto "corretta". In EF, è generalmente corretto utilizzare le proprietà della relazione al posto di uno dei due precedenti. Ad esempio, se si ha un oggetto Persona con un uno a molti a PhoneNumbers in una proprietà chiamata Person.PhoneNumbers, si potrebbe scrivere:

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

L'EF costruirà la unirsi per voi.

In termini della domanda precedente, il motivo per cui SQL generato è diverso è perché gli alberi di espressione sono diversi, anche se producono risultati equivalenti. Gli alberi di espressione sono mappati su SQL e ovviamente sai che puoi scrivere SQL diversi che producono gli stessi risultati ma con prestazioni diverse. La mappatura è progettata per produrre SQL decente quando si scrive una query EF "convenzionale".

Ma la mappatura non è così intelligente da prendere una query non convenzionale e ottimizzarla. Nella tua prima query, dichiari che gli oggetti devono essere equivalenti. Nel secondo, si specifica che la proprietà ID deve essere equivalente. La mia query di esempio sopra dice "ottieni solo i dettagli per questo record." L'EF è progettato per funzionare con il modo in cui mostro, principalmente, ma gestisce anche l'equivalenza scalare.

+0

Finalmente ha funzionato e capito un po 'meglio quello che sto cercando di fare - grazie. – Calanus

Problemi correlati