简体   繁体   English

实体框架 - 底层SQL语句

[英]entity framework - underlying SQL statement

Here's a simple linq query I executed in Entity framework 这是我在Entity框架中执行的一个简单的linq查询

    db.Responses.FirstOrDefault(r => r.QuestionId.Equals(“1.1.1”) && r.User.Id.Equals(user.Id)   && !r.IsDeleted);

Here QuestionId is a varchar datatype column, and db is the context object. 这里QuestionId是一个varchar数据类型列,db是上下文对象。

I fired up Entity profiler to see what was happening under the hood and underlying SQL query seem to have a bunch of statement that seemed a bit superfluous 我启动了实体分析器,看看底层发生了什么,底层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))

Notice all the extra code in lines 4-7, changing QuestionId to not null simplifies the query as so 注意第4-7行中的所有额外代码,将QuestionId更改为not null简化了查询

/* 1 */    SELECT TOP (1) *
/* 2 */    FROM   [dbo].[Responses] AS [Extent1]
/* 3 */    WHERE  ([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */)
/* 4 */    AND ('1.1.1' /* @p__linq__0 */ IS NOT NULL)
/* 5 */    AND ([Extent1].[UserId] = 1 /* @p__linq__1 */)
/* 6 */    AND (1 /* @p__linq__1 */ IS NOT NULL)
/* 7 */    AND ([Extent1].[IsDeleted] <> cast(1 as bit))

So, the question is why does entity framework put in all that extra code? 那么,问题是为什么实体框架会放入所有额外的代码? Why is line 4 & line 6 necessary, the only relevant statements in the where clause are line 3,5 and 7, 为什么第4行和第6行是必要的,where子句中唯一相关的语句是第3,5和7行,

I'm attempting to optimize my SQL statements and any thoughts on why entity framework is doing things this way would be helpful. 我正在尝试优化我的SQL语句,并且对于为什么实体框架以这种方式执行操作的任何想法都会有所帮助。 I'm using EF6 with Visual studio 2013. 我在Visual Studio 2013中使用EF6。

The lines: 线条:

/* 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)))

are supposed to account for the difference in semantics in null comparison between C#/VB.NET and SQL. 应该考虑C#/ VB.NET和SQL之间的空比较中语义的差异。 You can control the behavior using the DbContext.Configuration.UseDatabaseNullSemantics or ObjectContextOptions.UseCSharpNullComparisonBehavior . 您可以使用DbContext.Configuration.UseDatabaseNullSemanticsObjectContextOptions.UseCSharpNullComparisonBehavior来控制行为。 You can find more details here and here . 您可以在此处此处找到更多详细信息。

That is because string '1.1.1' is passed as sql command parameter and while the SQL generator knows nothing about value of parameter. 这是因为字符串'1.1.1'作为sql命令参数传递,而SQL生成器对参数值一无所知。 Ef does not generate different statements based on value. Ef不会根据值生成不同的语句。 Statement has to be correct even if passed value is null. 即使传递的值为null,语句也必须正确。

Equals has to be true if both, column and parameter value are null when Column is nullable. 如果Column可以为空,则列和参数值均为null时,等于必须为true。 And when it is not nullable, it can be true only if passed value is not null. 当它不可为空时,只有传递的值不为空时才可能为真。

Every thing that EF does is 100% valid and it is implemented very correctly. EF所做的每件事都是100%有效的,并且它的实现非常正确。 Don't try to optimize unless you are getting wrong result. 除非你得到错误的结果,否则不要尝试优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM