C# 实体框架-底层SQL语句
下面是我在实体框架中执行的一个简单的C# 实体框架-底层SQL语句,c#,sql,linq,entity-framework,C#,Sql,Linq,Entity Framework,下面是我在实体框架中执行的一个简单的linq查询 db.Responses.FirstOrDefault(r => r.QuestionId.Equals(“1.1.1”) && r.User.Id.Equals(user.Id) && !r.IsDeleted); 这里的QuestionId是一个varchar数据类型列,db是上下文对象 我启动了EntityProfiler来查看引擎盖下发生了什么,而底层SQL查询似乎有一大堆似乎有点多余的
linq
查询
db.Responses.FirstOrDefault(r => r.QuestionId.Equals(“1.1.1”) && r.User.Id.Equals(user.Id) && !r.IsDeleted);
这里的QuestionId
是一个varchar
数据类型列,db是上下文对象
我启动了EntityProfiler来查看引擎盖下发生了什么,而底层SQL查询似乎有一大堆似乎有点多余的语句
/* 1 */ SELECT TOP (1) *
/* 2 */ FROM [dbo].[Responses] AS [Extent1]
/* 3 */ WHERE ((([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */)
/* 4 */ AND (NOT ([Extent1].[QuestionId] IS NULL
/* 5 */ OR '1.1.1' /* @p__linq__0 */ IS NULL)))
/* 6 */ OR (([Extent1].[QuestionId] IS NULL)
/* 7 */ AND ('1.1.1' /* @p__linq__0 */ IS NULL)))
/* 8 */ AND ([Extent1].[UserId] = 1 /* @p__linq__1 */)
/* 9 */ AND (1 /* @p__linq__1 */ IS NOT NULL)
/* 10 */ AND ([Extent1].[IsDeleted] <> cast(1 as bit))
所以,问题是为什么实体框架会加入所有这些额外的代码?
为什么第4行和第6行是必要的,where条款中唯一相关的语句是第3、5和7行
我正在尝试优化我的SQL语句,任何关于EntityFramework为什么要这样做的想法都会很有帮助。我在Visual studio 2013中使用EF6。这是因为字符串“1.1.1”作为sql命令参数传递,而sql生成器对参数值一无所知。Ef不会根据值生成不同的语句。即使传递的值为null,语句也必须正确 当列可为null时,如果列和参数值都为null,则Equals必须为true。当它不可为null时,只有当传递的值不为null时,它才能为true EF所做的每一件事都是100%有效的,并且执行得非常正确。除非得到错误的结果,否则不要尝试进行优化。行:
/* 3 */ WHERE ((([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */)
/* 4 */ AND (NOT ([Extent1].[QuestionId] IS NULL
/* 5 */ OR '1.1.1' /* @p__linq__0 */ IS NULL)))
应该解释C#/VB.NET和SQL之间空比较的语义差异。您可以使用
DbContext.Configuration.UseDatabaseNullSemantics
或ObjectContextOptions.UseCSharpNullComparisonBehavior
控制行为。您可以找到更多详细信息和。比较值如何:r.QuestionId==“1.1.1”
?@WiktorZychla r.QuestionId==“1.1.1”没有区别,也不应该有区别。Equals和“==”都是等价的,r.QuestionId==“1.1.1”代码保持不变。我认为这并不意味着性能有很大的提高,但是有没有办法避免EF生成这些幼稚的语句?@e.campver性能是无用的如果逻辑错误,EF生成带有显式空值检查的语句的性能会更好,因为查询分析器会忽略空值的额外条件检查。
/* 3 */ WHERE ((([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */)
/* 4 */ AND (NOT ([Extent1].[QuestionId] IS NULL
/* 5 */ OR '1.1.1' /* @p__linq__0 */ IS NULL)))