为什么Entity框架会生成此SQL?

时间:2011-05-25 22:03:07

标签: sql linq-to-entities

我有这个LINQ语句,

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
                   };

它以这种形式生成SQL(LINQ to entities),

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

这是什么原因?我原本以为这样就足够了,

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

我记得LINQ to SQL倾向于生成更简单的SQL。

我已经查看了更复杂的连接等示例,LINQ to实体似乎生成了更复杂的SQL。

更新

这很有趣,因为我试图测试你在说什么,我遇到了这个LINQ,

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

这就产生了这个SQL,

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

这个没有子查询。

区别在于(至少其中一个)......等待它。 Informix的。上面生成子查询的第一个查询是使用informix。第二个查询不是SQL服务器。

它可能不那么简单,因为查询不同。

我确实接受了第二个查询并将其分解为像这样的子查询(手动),

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

SQL服务器为两者显示相同的执行计划,因此您说SQL服务器能够非常好地优化它。另一方面,Informix在优化方面是阴暗的。

1 个答案:

答案 0 :(得分:7)

它是否使用子查询生成SQL可能取决于您使用的实体框架提供程序。但由于大多数现有的谱系可能具有相同的谱系(因为它们可能是从Microsoft代码示例开始的),因此它们可能都会产生类似的SQL。提供者将获得一个查询树,该查询树由Linq语句生成,并负责生成SQL。执行此操作的过程是访问查询树中的节点并按原样生成SQL。

在OP的给定投影中,生成子查询是有意义的。它要求一组值(new ... {StartMetres,EndMetres})取自前面的“查询”。因此,查询生成将生成"SELECT <requested values> FROM something",其中"something"本身作为查询呈现。因此,查询树的简单访问会产生子查询。

完成该过程后,提供程序肯定可以“优化”生成的SQL并删除子查询。但是,这是SQL查询引擎真正擅长的事情,因此将该任务委派给查询引擎是有意义的。它可能取决于您使用的数据库,但是带有子查询的SQL语句的查询计划可能与没有子查询的“优化”查询计划相同。