【发布时间】:2011-10-19 14:29:00
【问题描述】:
为什么实体框架的 DbContext.Find() 会生成带有 select top 2 和派生表的查询?根据定义,查询是通过应该是唯一的主键来查找的。p>
【问题讨论】:
-
我今天被这个观察吓坏了:)很高兴你已经发布了这个:P
标签: .net sql entity-framework-4.1
为什么实体框架的 DbContext.Find() 会生成带有 select top 2 和派生表的查询?根据定义,查询是通过应该是唯一的主键来查找的。p>
【问题讨论】:
标签: .net sql entity-framework-4.1
Find 首先检查具有给定键的实体是否已经在上下文中。如果不是,它会查询数据库。在这种情况下,它可能使用使用SingleOrDefault 的LINQ 查询。 SingleOrDefault 转换为 SELECT TOP 2 以便能够在结果包含多个实体时引发异常。
那么,Find 为什么不使用FirstOrDefault(这将转换为SELECT TOP 1)。我不知道,但我猜Find 想检查该实体在数据库中是否真的是唯一的。它应该 - 因为它是查询使用的主键 - 但是模型和数据库可能不同步,因为有人更改了数据库中的主键,例如:将一列添加到数据库中的复合键而不是模型中。
真的只是一个假设。大概只有 EF 开发团队才能回答到底是什么原因。
编辑
如果我如上所述执行此操作(将列添加到 DB 中的复合键并在第一个键列中添加具有相同值的记录)然后调用 Find,我会收到异常...
序列包含多个元素
...还有这个堆栈跟踪:
//...
System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source)
System.Data.Entity.Internal.Linq.InternalSet`1.FindInStore(
WrappedEntityKey key, String keyValuesParamName)
System.Data.Entity.Internal.Linq.InternalSet`1.Find(Object[] keyValues)
System.Data.Entity.DbSet`1.Find(Object[] keyValues)
所以,看起来Find 确实使用了SingleOrDefault。
【讨论】: