2011-05-25 23 views
12

que tiene esta declaración de LINQ,¿Por qué el marco Entity genera este SQL?

var carriageways = from carriageway in dataModelCurrentEntities.Carriageway 
        where carriageway.RoadId == roadId && carriageway.DistanceBreak == false 
        orderby carriageway.CarriagewayStartInMetre 
        select new CarriagewaySummary 
        { 
         StartMetres = carriageway.CarriagewayStartInMetre, 
         EndMetres = carriageway.CarriagewayEndInMetre 
        }; 

Se genera SQL en esta forma (LINQ a las entidades),

SELECT 
Project1.field1 AS field1 
Project1.field2 AS field2 
FROM (SELECT 
    Extent1.field1 AS field1, 
    Extent1.field2 AS field2 
    FROM table AS Extent1 
    WHERE blah 
) AS Project1 
ORDER BY blah ASC 

¿Cuál es el razonamiento para esto? Yo hubiera pensado algo como esto era suficiente,

SELECT 
fields 
FROM table as Project1 
WHERE blah 
ORDER BY blah ASC 

Recuerdo que LINQ a SQL tendería a generar el SQL más simple.

He visto ejemplos más complicados con combinaciones, etc., y LINQ a entidades parece generar el SQL más complicado.

ACTUALIZACIÓN:

Es muy interesante porque yo estaba tratando de probar lo que está diciendo y me encontré con este LINQ,

var attachments = (from a in entities.Attachments 
        where a.AttachmentID == 749 
        select new {a.AddedOn, a.AddedBy}); 

y que genera este SQL,

SELECT 
[Extent1].[AttachmentID] AS [AttachmentID], 
[Extent1].[AddedOn] AS [AddedOn], 
[Extent1].[AddedBy] AS [AddedBy] 
FROM [dbo].[Attachment] AS [Extent1] 
WHERE 749 = [Extent1].[AttachmentID] 

Éste no tiene una sub-consulta.

La diferencia es (bueno, al menos uno de ellos) ... aguarde. Informix. La primera consulta arriba que genera la subconsulta usa informix. La segunda consulta que no es SQL server.

Puede que no sea tan simple porque las consultas son diferentes.

Me hizo tomar la segunda consulta y romperlo en una sub-consulta como esta (manualmente),

SELECT 
[Project1].[AttachmentID] AS [AttachmentID], 
[Project1].[AddedOn] AS [AddedOn], 
[Project1].[AddedBy] AS [AddedBy] 

    FROM (SELECT 

    [Extent1].[AttachmentID] AS [AttachmentID], 
    [Extent1].[AddedOn] AS [AddedOn], 
    [Extent1].[AddedBy] AS [AddedBy] 
    FROM [dbo].[Attachment] AS [Extent1] 
    WHERE 749 = [Extent1].[AttachmentID] 
    ) AS Project1 

servidor SQL muestra el mismo plan de ejecución para los dos, de modo que usted dice servidor SQL es capaz de optimizarlo bastante bien Informix, por otro lado, tiene sombra para optimizar las cosas.

Respuesta

7

Si se produce o no el SQL con la subconsulta, probablemente dependa del proveedor del marco de entidades que está utilizando. Pero dado que la mayoría de los existentes probablemente comparten el mismo pedigrí (en el sentido de que probablemente comenzaron a partir de una muestra de código de Microsoft), probablemente todos resulten en SQL similar. El proveedor recibe un árbol de consulta que se produce a partir de la declaración Linq y es responsable de producir el SQL. El proceso para hacer esto es visitar los nodos en el árbol de consultas y generar SQL a medida que avanza.

En la proyección dada en el PO, tiene sentido que se genere la subconsulta. Está pidiendo un conjunto de valores (nuevo ... {StartMetres, EndMetres}) que están tomados de la "consulta" precedente. La generación de consultas produciría así "SELECT <requested values> FROM something" donde el "something" es, en sí mismo, representado como una consulta. La simple visita del árbol de consulta, por lo tanto, da como resultado una subconsulta.

Una vez que el proceso haya finalizado, sin duda será posible para el proveedor "optimizar" el SQL resultante y eliminar la subconsulta. Sin embargo, ese es el tipo de cosas que los motores de consulta SQL son realmente buenos, por lo que tiene sentido delegar esa tarea en el motor de consulta. Probablemente dependa de la base de datos que está utilizando, pero es probable que el plan de consulta de la declaración SQL con la subconsulta sea idéntico al de la "optimizada" sin la subconsulta.

Cuestiones relacionadas