EF 4.1 code-first: разница между EF-сгенерированным sql и custom sql - PullRequest
1 голос
/ 14 октября 2011

У меня есть вопрос о sql, сгенерированном Entity Framework, и о рукописном. В моем проекте у меня есть несколько сущностей (они на самом деле не важны для этого Q), для простого примера, когда я использую этот код:

var query = context.Employees.Select(e => new {
                PersonalCode = e.PersonelCode,
                Fname = e.Person.Fname,
                Family = e.Person.Family,
                Email = e.Person.Emails
            });

сгенерированный sql выглядит примерно так:

SELECT 
[Project1].[EmployeeID] AS [EmployeeID], 
[Project1].[EmployeeID1] AS [EmployeeID1], 
[Project1].[PersonID] AS [PersonID], 
[Project1].[EmployeeID2] AS [EmployeeID2], 
[Project1].[PersonID1] AS [PersonID1], 
[Project1].[PersonelCode] AS [PersonelCode], 
[Project1].[Fname] AS [Fname], 
[Project1].[Family] AS [Family], 
[Project1].[C1] AS [C1], 
[Project1].[EmailID] AS [EmailID], 
[Project1].[Mail] AS [Mail]
FROM ( SELECT 
    [Extent1].[EmployeeID] AS [EmployeeID], 
    [Extent1].[PersonelCode] AS [PersonelCode], 
    [Join1].[PersonID] AS [PersonID], 
    [Join1].[Fname] AS [Fname], 
    [Join1].[EmployeeID] AS [EmployeeID1], 
    [Join3].[PersonID] AS [PersonID1], 
    [Join3].[Family] AS [Family], 
    [Join3].[EmployeeID] AS [EmployeeID2], 
    [Join5].[EmailID1] AS [EmailID], 
    [Join5].[Mail] AS [Mail], 
    CASE WHEN ([Join5].[EmailID2] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM    [dbo].[Employees] AS [Extent1]
    LEFT OUTER JOIN  (SELECT [Extent2].[PersonID] AS [PersonID], [Extent2].[Fname] AS [Fname], [Extent3].[EmployeeID] AS [EmployeeID]
        FROM  [dbo].[Persons] AS [Extent2]
        LEFT OUTER JOIN [dbo].[Employees] AS [Extent3] ON [Extent2].[PersonID] = [Extent3].[EmployeeID] ) AS [Join1] ON [Extent1].[EmployeeID] = [Join1].[PersonID]
    LEFT OUTER JOIN  (SELECT [Extent4].[PersonID] AS [PersonID], [Extent4].[Family] AS [Family], [Extent5].[EmployeeID] AS [EmployeeID]
        FROM  [dbo].[Persons] AS [Extent4]
        LEFT OUTER JOIN [dbo].[Employees] AS [Extent5] ON [Extent4].[PersonID] = [Extent5].[EmployeeID] ) AS [Join3] ON [Extent1].[EmployeeID] = [Join3].[PersonID]
    LEFT OUTER JOIN  (SELECT [Extent6].[EmailID] AS [EmailID2], [Extent6].[PersonID] AS [PersonID], [Extent7].[EmailID] AS [EmailID1], [Extent7].[Mail] AS [Mail]
        FROM  [dbo].[EmailsForPersons] AS [Extent6]
        INNER JOIN [dbo].[Emails] AS [Extent7] ON [Extent6].[EmailID] = [Extent7].[EmailID] ) AS [Join5] ON [Join5].[PersonID] = [Extent1].[EmployeeID]
)  AS [Project1]
ORDER BY [Project1].[EmployeeID] ASC, [Project1].[EmployeeID1] ASC, [Project1].[PersonID] ASC, [Project1].[EmployeeID2] ASC, [Project1].[PersonID1] ASC, [Project1].[C1] ASC

но по этому коду:

SELECT     Employees.PersonelCode, Persons.Fname, Persons.Family, Emails.Mail
FROM         Employees 
                        LEFT OUTER JOIN     -- or: INNER JOIN
                        Persons ON Employees.EmployeeID = Persons.PersonID 
                                LEFT OUTER JOIN
                                EmailsForPersons ON Persons.PersonID = EmailsForPersons.PersonID 
                                            LEFT OUTER JOIN
                                            Emails ON EmailsForPersons.EmailID = Emails.EmailID

Я дам тот же результат! В чем разница между этими кодами? Какие из них имеют более высокую производительность и более высокую скорость?

1 Ответ

2 голосов
/ 14 октября 2011

Вы можете проанализировать и отобрать два запроса, чтобы увидеть, какие из них работают лучше?

См. Также Как очистить и оптимизировать код, сгенерированный службой ODF WCF?

SQL, генерируемый EF, является очень общим и должен работать в различных ситуациях.По какой-то причине это очень многословно.Он часто имеет вложенную структуру SELECT [Col1] FROM (SELECT [Col1] ...) и множество операторов CAST для сравнений.

Делается ли это для обеспечения максимальной совместимости и минимальной вероятности того, что чей-то хитрый запрос не сможет быть переведен, илиэто сделано потому, что код, который генерирует SQL, намного яснее и проще, мы можем только догадываться.Это проектное решение, принятое в команде Entity Framework.

Честно говоря, я бы не стал беспокоиться об этом , если только вы не протестируете два запроса параллельно на производительность с помощью анализатора запросов.Я ожидал бы очень минимальной разницы между ними.

Если производительность сгенерированного запроса хуже, тогда самый простой шаблон - написать логику внутри хранимой процедуры и заставить EF вызывать хранимую процедуру.Это отнимает у EF все управление и передает его в ваши руки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...