为什么Entity Framework生成缓慢过度编程的SQL?

时间:2012-10-09 11:58:21

标签: c# .net sql entity-framework linq-to-entities

我有这段代码:

DbSet<TableName> table = ...// stored reference

var items = from n in table where
            n.Name.ToUpper().Contains(searchString.ToUpper().Trim())
            select n;
WriteToLog( items.ToString() );

最后一行输出生成的SQL。这是我得到的:

SELECT 
    [Extent1].[Name] AS [Name],
    // all the other columns follow
FROM (SELECT 
  [TableName].[Name] AS [Name],
  // all the other columns follow
FROM [dbo].[TableName] AS [TableName]) AS [Extent1]
WHERE ( CAST(CHARINDEX(LTRIM(RTRIM(UPPER(@p__linq__0))), UPPER([Extent1].[Name])) AS int)) > 0

你知道,有SELECT - 来自 - SELECT虽然它完全是多余的 - 但SELECT就足够了。使用EF的代码运行时间超过半分钟,并且该查询超时,尽管表格相当小。

为什么会生成这种过度设计的SQL查询,如何让EF生成更好的查询?

2 个答案:

答案 0 :(得分:8)

它通过转换表达式树来生成结果SQL。它似乎过度设计(例如,使用子查询)作为转换完成方式的副作用。 转换的细节是专有的和复杂的,结果不应该是人类可读的。

问题并不完全清楚 - 你正试图解决我认为可能不是问题的问题。尝试将生成的查询与您自己的查询进行比较 - 我猜想查询优化器会做出如此简单优化的简短工作。

我的猜测(这可能是你可以得到的最好的答案,除非LINQ to Entities MS dev出现)是他们正在做的那样:产生最有效的查询,但留下令人头疼的 - 将查询优化到他们已经将数百或数千个工作日放入的位的困难工作:SQL Server中的查询优化器。

答案 1 :(得分:3)

它执行额外的Select但是选择没有相关费用。您可以查看估算的查询计划,并在其中显示0%费用。这样做是因为EF与Oracle,SQL服务器等各种RDBMS系统兼容,并确保它可能实现最大兼容性。

但是我确实同意Entity Framework生成UGLY sql。您提供的示例是一个非常简单的Linq查询,当您的查询开始变得复杂时,您会看到更多的丑陋。

1)虽然这可能会或可能不会回答您的答案,但我会说使用像PetaPoco这样的微型ORM:

https://github.com/toptensoftware/PetaPoco

或Dapper.Net

https://github.com/SamSaffron/dapper-dot-net

我一直在我的一个项目中使用它,我完全满意你用简单的Ado.Net获得的原始速度。

2)我的第二个建议是始终使用至少 Select语句的存储过程。对于插入,更新和删除,您应该使用EF并利用更改跟踪机制,这样可以节省您编写繁琐查询的时间,但至少应该尝试使用纯SQL的Select语句,这使您可以更自由地使用SQL产生。