Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么实体框架会生成缓慢的、过度工程化的SQL?_C#_.net_Sql_Entity Framework_Linq To Entities - Fatal编程技术网

C# 为什么实体框架会生成缓慢的、过度工程化的SQL?

C# 为什么实体框架会生成缓慢的、过度工程化的SQL?,c#,.net,sql,entity-framework,linq-to-entities,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() ); 你看,这里有SELECT-from-SELECT,虽然它是

我有以下代码:

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

var items = from n in table where
            n.Name.ToUpper().Contains(searchString.ToUpper().Trim())
            select n;
WriteToLog( items.ToString() );
你看,这里有
SELECT
-from-
SELECT
,虽然它是完全冗余的-一个
SELECT
就足够了。使用EF的代码运行时间超过半分钟,并且在该查询上超时,尽管表非常小


为什么会生成这种过度工程化的SQL查询?如何使EF生成更好的查询?

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

这个问题并不完全清楚——你正在试图解决一个我认为可能不是问题的问题。尝试将生成的查询与您自己的查询进行比较-我猜查询优化程序将很快完成这样一个简单的优化


我的猜测是(这可能是你在这里能得到的最好的答案,除非出现一个LINQ to Entities MS dev)他们正在做的就是:生成最有效的查询,但是,将优化查询这一令人头疼的困难工作留给他们已经投入了数百或数千个工作日的部分:SQL Server中的查询优化程序。

它会额外执行
Select
,但Select没有相关成本。您可以看到估计的查询计划,它将显示该计划中的
0%
成本。这是因为EF与各种RDBMS系统(如Oracle、SQL server)兼容,为了确保最大的兼容性,它可能会这样做

然而,我同意实体框架生成丑陋的sql。您给出的示例是一个非常简单的Linq查询,当您的查询开始变得复杂时,您将看到更多的丑陋

1)虽然这可能回答您的问题,也可能无法回答您的问题,但我想说的是,使用类似PetaPoco的微型ORM:

还是简洁的.Net

我已经在我的一个项目中使用了它,我完全满意使用普通Ado.Net所获得的原始速度


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

查询优化程序将很快完成这项工作。我想说的是,它生成的代码不是人类可读的,但这不是问题,因为它不是设计用来这样做的。如果您有一些经过测量的证据表明SQL的速度很慢,那就太好了,但我认为它不是,您错了。是吗?至于如何改进它,我建议
searchString.ToUpper().Trim()
应该在查询之外进行解析,这样就不会将这项工作转移到sql上server@sharptooth那根绳子看起来相当长,但如果没有尺子或另一根绳子,相比之下,它可能会非常短。。(你的那根绳子有多长?你用什么来衡量它?)我同意基伦的观点。子查询的效果很难测量,并且在查询计划缓存中几乎不存在。任何性能问题都将由
WHERE
子句引起-它将完全混淆任何可用索引。如果您能够重构数据,使其不需要使用
UPPER
CONTAINS
,那么您的查询将更加SQL友好。这可能是不可能的,但使用这两种方法都会带来巨大的性能影响。)[您实际上是在做像“%xxx%”这样的
Name
,任何有SQL经验的人都会告诉您这就是问题所在。]好的方面,但是混合使用SQL和EF会给我带来麻烦opinion@KierenJohnstone这实际上取决于自定义SQL查询结果的预期用途。例如,我可以显示存储过程的结果列表,这比依靠EF进行最有效的查询提供了更多的控制。如果我没有实际使用存储过程的结果,然后通过EF进行更新以保存回DB,我看没有问题。
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