Подтвердить что ты не робот

Почему инфраструктура Entity генерирует этот SQL?

У меня есть оператор 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 для сущностей),

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 для сущностей, похоже, сгенерирует более сложный SQL.

UPDATE:

Это довольно интересно, потому что я пытался проверить, что вы говорите, и я столкнулся с этим 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, с другой стороны, является теневым при оптимизации вещей.

4b9b3361

Ответ 1

Независимо от того, создает ли SQL SQL с подзапросом, вероятно, зависит от используемого вами поставщика инфраструктуры сущностей. Но так как большинство существующих, вероятно, имеют одну и ту же родословную (в которой они, вероятно, начинались с образца кода Microsoft), они, вероятно, все приводят к аналогичному SQL. Поставщику дается дерево запросов, которое создается из инструкции Linq и отвечает за создание SQL. Процесс для этого заключается в том, чтобы посещать узлы в дереве запросов и генерировать SQL по мере его использования.

В данной проекции в OP имеет смысл, что подзапрос генерируется. Он запрашивает набор значений (new... {StartMetres, EndMetres}), которые берутся из предыдущего "запроса". Таким образом, генерация запросов создаст "SELECT <requested values> FROM something", где "something" сам будет отображаться как запрос. Простое посещение дерева запросов, таким образом, приводит к подзапросу.

Как только этот процесс будет завершен, провайдеру будет "оптимизировать" полученный SQL и удалить подзапрос. Тем не менее, это то, на что отлично работают SQL-запросы, поэтому имеет смысл делегировать эту задачу механизму запросов. Вероятно, это зависит от используемой вами базы данных, но вполне вероятно, что план запроса для оператора SQL с подзапросом будет идентичен "оптимизированному" без подзапроса.