2009-08-06 15 views
6

Esta pregunta sigue desde un question Ayer pregunté por qué el uso de la consulta de combinación en mis Entidades produjo SQL terriblemente complicado. Parecía que la realización de una consulta como esta:¿Cuál es la diferencia entre usar Join in Linq y la sintaxis de unión previa a 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; 

produjo el SQL horrible que tomó 18 segundos para correr en la base de datos, mientras que unirse a las entidades a través de una cláusula where (una especie de sintaxis SQL pre-ANSI) tomó menos de un segundo para correr y produce el mismo resultado

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

he buscado en google en todo, pero todavía no entiendo por qué el segundo es diferente de SQL produce a la primera. ¿Puede alguien explicarme la diferencia por favor? ¿Cuándo debo utilizar la palabra clave se unen


Este es el SQL que se produce cuando Se unen en mi consulta y tardó 18 segundos en ejecutarse:

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 

Este es el SQL que se producen utilizando la sintaxis ANSI Estilo (y es bastante cerca de lo que escribiría si estuviera escribiendo el mismo 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 
+0

Una gran pregunta. – tomfanning

+0

¿Qué DB estás usando? ¿Cómo se ve el código SQL? – AnthonyWJones

Respuesta

4

Ninguna de las consultas anteriores es completamente "correcta". En EF, generalmente es correcto usar las propiedades de relación en lugar de cualquiera de las anteriores. Por ejemplo, si usted tenía un objeto Persona con una relación de uno a muchos a PHONENUMBERS en una propiedad llamada Person.PhoneNumbers, se podría escribir:

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

El EF construirá la unión para usted.

En términos de la pregunta anterior, la razón por la que el SQL generado es diferente se debe a que los árboles de expresión son diferentes, a pesar de que producen resultados equivalentes. Los árboles de expresiones se asignan a SQL y, por supuesto, usted sabe que puede escribir diferentes SQL que produzcan los mismos resultados pero con un rendimiento diferente. El mapeo está diseñado para producir un SQL decente cuando se escribe una consulta EF farily "convencional".

Pero la asignación no es tan inteligente como para tomar una consulta poco convencional y optimizarla. En su primera consulta, declara que los objetos deben ser equivalentes. En el segundo, usted declara que la propiedad de identificación debe ser equivalente. Mi consulta de muestra anterior dice "solo obtenga los detalles de este registro". El EF está diseñado para funcionar con la forma en que lo muestro, principalmente, pero también maneja bien la equivalencia escalar.

+0

Finalmente lo conseguí trabajando y entendiendo un poco mejor lo que estoy tratando de hacer, gracias. – Calanus

Cuestiones relacionadas