Почему Entity Framework DbContext.Find() генерирует запрос с помощью select top 2?

Почему Entity Framework DbContext.Find() генерирует запрос с помощью select top 2 и производной таблицы? По определению запрос просматривает первичный ключ, который должен быть уникальным.

Ответ 1

Find проверяет сначала, если объект с данным ключом уже находится в контексте. Если он не запрашивает базу данных. Возможно, в этом случае он использует запрос LINQ с помощью SingleOrDefault. SingleOrDefault переводит на SELECT TOP 2, чтобы иметь возможность генерировать исключение, если результат имеет более одного объекта.

Итак, почему Find не использует FirstOrDefault (который переводится на SELECT TOP 1). Я не знаю, но я бы предположил, что Find хочет проверить, что сущность действительно уникальна в базе данных. Он должен - потому что это первичный ключ, используемый в запросе, - но модель и база данных могут быть не синхронизированы, потому что кто-то изменил первичный ключ в базе данных, например: добавил столбец к составному ключу в базе данных, но не в модели.

На самом деле просто гипотеза. Возможно, только команда разработчиков EF может ответить, в чем именно причина.

Edit

Если я сделаю это, как описано выше (добавьте столбец в составной ключ в БД и добавьте запись с тем же значением в первом ключевом столбце) и вызовите затем 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.