90

У меня есть чертовски время, когда мы находим сравнение различных способов запроса отдельного элемента и использования каждого из них.Entity Framework 4 Single() vs First() vs FirstOrDefault()

У кого-нибудь есть ссылка, которая сравнивает все эти данные, или краткое объяснение того, почему вы будете использовать один над другим? Есть ли еще больше операторов, о которых я не знаю?

спасибо.

ответ

157

Вот краткий обзор различных методов:

  • Find() - если вы хотите получить деталь первичного ключа. Это вернет null, если он не может найти элемент. Он будет выглядеть в контексте перед тем, как перейти к базе данных (как отметил Ярон в комментариях), что может быть важным фактором эффективности, если вам нужно получить один и тот же объект несколько раз, пока тот же контекст жив.

  • Single() - когда вы ожидаете, что только один элемент будет возвращен запросом. Это вызовет исключение, если запрос не возвращает ровно один элемент.

  • SingleOrDefault() - когда вы ожидаете, что нулевой или один элемент будет возвращен запросом (т. Е. Вы не уверены, существует ли элемент с заданным ключом). Это вызовет исключение, если запрос не возвращает ноль или один элемент.

  • Первый() - когда вы ожидаете, что один или несколько элементов будут возвращены запросом, но вы хотите получить доступ к первому элементу вашего кода (заказ может быть важным в запросе здесь). Это вызовет исключение, если запрос не возвращает хотя бы один элемент.

  • FirstOrDefault() - когда вы ожидаете, что запрос будет возвращен ноль или более, но вы хотите получить доступ к первому элементу вашего кода (т. Е. Вы не уверены, существует ли элемент с заданным ключом)

+2

А, спасибо. Еще одна, которая, похоже, выполняет одно и то же - lol. – asfsadf

+0

Используете ли вы все 4 в зависимости от сценария или придерживаетесь только одного? – asfsadf

+1

Это зависит от сценария. Если вы знаете, что вы всегда должны получать одну запись из db, не более, не менее, для данного запроса, тогда Single() является «правильным» для использования. В других ситуациях другие могут быть более уместными. В предыдущих версиях EF мы ограничивались First() и FirstOrDefault(), которые работают для сценариев, в которых вы ожидаете единственную запись, но они не будут предупреждать вас, если вы действительно получите больше одной записи, что может быть важно в зависимости от ситуация. –

15

Это действительно очень просто: Single возвращает один элемент и генерирует исключение, если нет ни одного, ни одного элемента. First вернет первый элемент или бросок, когда нет элемента. FirstOrDefault вернет первый элемент или вернет значение по умолчанию (которое равно null, если данный тип является ссылочным типом), когда нет элемента.

Это поведение, которое должен иметь API. Обратите внимание, однако, что базовая реализация может иметь другое поведение. Хотя Entity Framework подчиняется этому, O/RM, например LLBLGen, может также возвращать null при вызове First, что очень странно. Это было очень странное (и упрямое) решение дизайнера ИМО.

+0

Спасибо Стивен. Наверное, мне все еще интересно, почему ты должен использовать один над другим? Я всегда использовал FirstOrDefault(), и мне было любопытно, почему многие новые примеры, которые я видел, переключились на Single(). Есть ли причина переключиться на Single()? Есть ли другие, которые также выполняют то же самое, что я должен рассмотреть вместо этого? – asfsadf

+7

Если вам нравится ваш код «fail fast», First() и Single(), пусть ваш код более точно скажет, что ожидается (так что он может потерпеть неудачу в противном случае) –

+3

Я полностью согласен с Фрэнком. Это также касается сообщения о намерениях. 'Single' четко выражает, что вы ожидаете, что результат будет иметь один элемент. – Steven

8

Каждый из четырех способов имеет свое место; Хотя у вас действительно есть только две разные операции.

  • Во-первых - Ожидая набор результатов, содержащий несколько элементов, дайте мне первый элемент в этом наборе.
  • Одинокий - Ожидая один результат назад, дайте мне этот предмет.

Версия xxxxOrDefault() просто добавляет: «Я не хочу рассматривать пустой набор результатов как исключительное обстоятельство.«

+0

ОК, так мне кажется, что First() редко пригодится. Мне трудно найти сценарий, когда Single() не будет первым вариантом. У вас есть быстрая раздача, случайно? Благодарю. – asfsadf

+3

К сожалению, многие разработчики используют First() или FirstOrDefault() исключительно как защитную меру, думая, что это позволит избежать исключения, когда у него действительно есть потенциал, чтобы скрыть реальные проблемы. –

16

Я всегда стараюсь использовать FirstOrDefault.Если вы действительно хотите быть придирчивым к производительности, тогда вы должны использовать FirstOrDefault в EF. Под обложками SingleOrDefault использует верхний (2) запрос, потому что ему нужно проверить, есть ли второй ряд, который соответствует критериям, и если это произойдет, он вызывает исключение. в основном в SingleOrDefault вы говорите, что и все равно бросить исключение, если ваш запрос возвращает более 1 запись.

+4

Вы когда-либо измеряли разницу в производительности между «FirstOrDefault» и «SingleOrDefault», чтобы быть значительными? Я бы сказал, что это преждевременная оптимизация в большинстве случаев. – Steven

+1

[Этот парень сделал] (http://stackoverflow.com/a/8265919/634824) –

0

Single() и SingleOrDefault() обычно используется для уникальных идентификаторов, таких как идентификаторы, а Первый() или FirstOrDefault() обычно используется для запроса, который может иметь несколько результатов, но вы хотите только «Top 1».

Single() или First() бы бросить исключение, если результат не возвращается, SingleOrDefault() и FirstOrDefault() перехватывает исключение и возвращает нуль или по умолчанию (ResultDataType).

1

С другой стороны, вы можете разделить эти методы, с помощью базовой логики, например:

  • метод будет запрашивать базу данных непосредственно: холост(), SingleOrDefault(), First(), FirstOrDefault()
  • метод будет выполнять поиск в кэше еще до выдачи запроса к базе данных: Find()

Для некоторых деталей производительности, особенно во втором случае вы можете посмотреть здесь: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Кроме того, в первой группе можно задавать сложные запросы, но с Find() метода вы можете предоставить только юридическое лицо ключ для поиска.

Смежные вопросы