为啥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 转换为小数?