[英]entity framework - underlying SQL statement
这是我在Entity框架中执行的一个简单的linq
查询
db.Responses.FirstOrDefault(r => r.QuestionId.Equals(“1.1.1”) && r.User.Id.Equals(user.Id) && !r.IsDeleted);
这里QuestionId
是一个varchar
数据类型列,db是上下文对象。
我启动了实体分析器,看看底层发生了什么,底层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-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))
那么,问题是为什么实体框架会放入所有额外的代码? 为什么第4行和第6行是必要的,where子句中唯一相关的语句是第3,5和7行,
我正在尝试优化我的SQL语句,并且对于为什么实体框架以这种方式执行操作的任何想法都会有所帮助。 我在Visual Studio 2013中使用EF6。
线条:
/* 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
来控制行为。 您可以在此处和此处找到更多详细信息。
这是因为字符串'1.1.1'作为sql命令参数传递,而SQL生成器对参数值一无所知。 Ef不会根据值生成不同的语句。 即使传递的值为null,语句也必须正确。
如果Column可以为空,则列和参数值均为null时,等于必须为true。 当它不可为空时,只有传递的值不为空时才可能为真。
EF所做的每件事都是100%有效的,并且它的实现非常正确。 除非你得到错误的结果,否则不要尝试优化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.