EF 4.1代码优先:EF生成的sql和自定义sql之间的区别

发布于 2024-12-10 05:40:16 字数 3219 浏览 1 评论 0原文

我有一个关于实体框架生成的sql和手写sql的问题。在我的项目中,我有一些实体(它们对于这个问题来说并不重要),举一个简单的例子,当我使用这段代码时:

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

我会给出相同的结果结果!这些代码有什么区别?哪一个性能更高、速度更快?

I have a question about sql generated by Entity Framework and the hand-writed one. In my project, I have some entities (they aren't important really for this Q), for a simple example, when I use this code:

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

the generated sql is something like this:

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

but by this code:

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

I'll give the same result! What is difference between these codes? Which one have a higher performance and higher speed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

掩耳倾听 2024-12-17 05:40:16

您可以对这两个查询进行分析和采样,看看哪个性能更好?

另请参阅如何清理和优化优化 WCF OData 服务生成的代码?

EF 生成的 SQL 非常通用,需要在各种情况下工作。无论出于何种原因,它都非常冗长。它通常具有 SELECT [Col1] FROM (SELECT [Col1] ...) 嵌套结构,以及大量用于比较的 CAST 语句。

这样做是否是为了确保最大的兼容性和最小化某人棘手的查询无法被翻译的可能性,还是因为生成 SQL 的代码更加清晰和简单,我们只能猜测。这是实体框架团队内部做出的设计决策。

坦率地说,我根本不担心这个问题,除非您使用查询分析器并排测试两个查询的性能。我预计两者之间的差异非常小。

如果生成的查询的性能较差,那么最简单的模式是将逻辑编写在存储过程中,并让 EF 调用存储过程。这将所有控制权从 EF 手中夺走,并交到您手中。

You can analysed and sampled the two queries to see which performs better?

See also How to clean & optimise code generated by WCF OData service?

The SQL generated by EF is very generic and needs to work in a variety of situations. For whatever reason, it is very verbose. It often has a SELECT [Col1] FROM (SELECT [Col1] ...) nested structure, and lots of CAST statements for comparisons.

Whether this is done to ensure maximum compatibility and minimum chance of someone's tricky query not being able to be translated, or whether it's done because the code that generates the SQL is much clearer and simpler, we can only guess. It's a design decision made within the Entity Framework team.

Frankly I wouldn't worry about this at all unless you test the two queries side-by-side for performance using query analyser. I would expect very minimal difference between the two.

If the performance is worse for the generated query then the simplest pattern is to write the logic inside a stored procedure and have EF call the stored procedure. This takes all the control away from EF and puts it in your hands.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文