为什么Entity Framework的DbContext.Find()使用select top 2和派生表生成查询?根据定义,查询是通过主键查找的,主键应该是唯一的。
答案 0 :(得分:18)
Find
首先检查具有给定键的实体是否已在上下文中。如果没有,它会查询数据库。在这种情况下,它可能使用SingleOrDefault
的LINQ查询。如果结果包含多个实体,SingleOrDefault
会转换为SELECT TOP 2
以便能够抛出异常。
那么,为什么不Find
使用FirstOrDefault
(这会转换为SELECT TOP 1
)。我不知道,但我猜想Find
想要检查该实体在数据库中是否真的是唯一的。它应该 - 因为它是查询使用的主键 - 但是模型和数据库可能不同步,因为有人更改了数据库中的主键,例如:向数据库中的复合键添加了列,但未在模型中添加。
真的只是一个假设。只有EF开发团队可能会回答原因。
修改强>
如果我按上述方法执行此操作(在DB中添加列复合键并在第一个键列中添加具有相同值的记录)然后调用Find
,我会得到例外...
序列包含多个元素
...和这个stacktrace:
//...
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
。