2011-05-25 1 views
12

J'ai cette déclaration LINQ,Pourquoi le framework Entity génère-t-il ce 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 
        }; 

Il génère SQL sous cette forme (LINQ aux entités),

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 

Quel est le raisonnement pour cela? J'aurais pensé que quelque chose comme cela suffisait,

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

Je rappelle que LINQ to SQL aurait tendance à générer le plus simple SQL. J'ai regardé des exemples plus compliqués avec des jointures etc, et LINQ to entities semble générer le SQL plus compliqué.

MISE À JOUR:

Il est très intéressant parce que j'ai essayé de tester ce que vous dites et je suis tombé sur ce LINQ,

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

Et qui génère ce SQL,

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

Celui-ci n'a pas de sous-requête. La différence est (bien l'un d'entre eux au moins) ... attendez-le. Informix. La première requête ci-dessus qui génère la sous-requête utilise informix. La deuxième requête qui n'est pas le serveur SQL.

Cela peut ne pas être aussi simple que cela parce que les requêtes sont différentes.

J'ai pris la deuxième requête et le casser dans une sous-requête comme ceci (manuellement),

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 

serveur SQL montre le même plan d'exécution pour les deux, afin que vous dites serveur SQL est capable de optimisez-le plutôt bien. Informix d'autre part est ombragé à l'optimisation des choses.

Répondre

7

La nature du SQL avec la sous-requête dépend probablement du fournisseur de structure d'entité que vous utilisez. Mais puisque la plupart des existants partagent probablement le même pedigree (en ce sens qu'ils ont probablement commencé à partir d'un échantillon de code Microsoft), ils aboutissent probablement tous à un SQL similaire. Le fournisseur reçoit un arbre de requête produit à partir de l'instruction Linq et responsable de la production du code SQL. Le processus pour ce faire est de visiter les nœuds dans l'arbre de requête et de générer du SQL au fur et à mesure.

Dans la projection donnée dans l'OP, il est logique que la sous-requête soit générée. Il demande un ensemble de valeurs (nouveau ... {StartMetres, EndMetres}) qui sont extraites de la "requête" précédente. La génération de requête produirait donc "SELECT <requested values> FROM something" où le "something" est, lui-même, rendu comme une requête. La simple visite de l'arbre de requête entraîne donc une sous-requête.

Une fois ce processus terminé, il serait certainement possible pour le fournisseur d '"optimiser" le SQL résultant et de supprimer la sous-requête. Cependant, c'est le genre de chose que les moteurs de requête SQL sont vraiment bons, il est donc logique de déléguer cette tâche au moteur de recherche. Cela dépend probablement de la base de données que vous utilisez, mais il est probable que le plan de requête pour l'instruction SQL avec la sous-requête sera identique à celui "optimisé" sans la sous-requête.

Questions connexes