为啥Entity Framework没有在使用SingleOrDefault时生成的SQL中添加“where”?

Posted

技术标签:

【中文标题】为啥Entity Framework没有在使用SingleOrDefault时生成的SQL中添加“where”?【英文标题】:Why doesn't Entity Framework add a "where" to the SQL generated when SingleOrDefault is used?为什么Entity Framework没有在使用SingleOrDefault时生成的SQL中添加“where”? 【发布时间】:2011-03-01 12:46:22 【问题描述】:

我正在使用带有“仅代码”的实体框架 CTP 5(使用 SQL Server 2008)。我有一个从 DbContext 返回的实体,然后我从中访问一个子集合,并从中选择一个项目。这是我的 LINQ 语句:

Question currentQuestion = currentTopic.Questions.SingleOrDefault(x => x.IsCurrent);

这会产生以下 SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[CreatedAt] AS [CreatedAt], 
[Extent1].[IsCurrent] AS [IsCurrent], 
[Extent1].[Xml] AS [Xml], 
[Extent1].[TopicId] AS [TopicId]
FROM [dbo].[Questions] AS [Extent1]
WHERE [Extent1].[SessionId] = 24

我的“IsCurrent”限制根本没有被引用。 IsCurrent 是我数据库中的一个位字段。

谁能解释这是为什么?这对性能造成了巨大影响。

【问题讨论】:

不确定... x => x.IsCurrent == true 【参考方案1】:

这是所有 EF 实现的设计。问题集合公开IEnumerable<Question> 而不是IQueryable<Question>。当您访问 Questions 属性时,会触发延迟加载并加载所有相关问题。然后你在加载的集合上调用SingleOrDefault

如果您只想要一个问题,请改为运行此查询:

var question = context.Questions
                 .SingleOrDefault(q => q.Session.Id == sessionId && q.IsCurrent);

【讨论】:

【参考方案2】:

我认为是因为子集合 (currentTopic.Questions) 被延迟加载完全,然后在您的集合上调用了 SingleOrDefault 的 LINQ to Object 版本而不是 LINQ to Entities 版本。

您发布的 SQL 语句包含 WHERE [Extent1].[SessionId] = 24。这表明它正在为您的 currentTopic 加载所有问题。

【讨论】:

以上是关于为啥Entity Framework没有在使用SingleOrDefault时生成的SQL中添加“where”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要使用 Attach 来更新 Entity Framework 6?

为啥在我运行迁移时 Entity Framework 包会自动更新?

为啥我的 Entity Framework Code First 代理集合为空,为啥我不能设置它?

使用 MySQL 时,为啥 Entity Framework 4 试图将 long 转换为小数?

为啥运行时表达式会导致 Entity Framework Core 5 的缓存发生冲突?

为啥我必须为 Code First / Entity Framework 提供无参数构造函数