Рассмотрим методы расширения IEnumerable SingleOrDefault()
иFirstOrDefault()
MSDN документы, которыеSingleOrDefault
:
Возвращает единственный элемент последовательности или значение по умолчанию, если последовательность пуста; этот метод генерирует исключение, если в последовательности более одного элемента.
в то время как FirstOrDefault
из MSDN (предположительно при использовании OrderBy()
или OrderByDescending()
или вообще ничего),
Возвращает первый элемент последовательности
Рассмотрим несколько примеров запросов, не всегда понятно, когда использовать эти два метода:
var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE
var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?
Вопрос
Какие соглашения вы соблюдаете или предлагаете при принятии решения об использовании SingleOrDefault()
и FirstOrDefault()
в своих запросах LINQ?
источник
Если ваш набор результатов возвращает 0 записей:
SingleOrDefault
возвращает значение по умолчанию для типа (например, значение по умолчанию для int равно 0)FirstOrDefault
возвращает значение по умолчанию для типаЕсли ваш набор результатов возвращает 1 запись:
SingleOrDefault
возвращает эту записьFirstOrDefault
возвращает эту записьЕсли ваш набор результатов возвращает много записей:
SingleOrDefault
бросает исключениеFirstOrDefault
возвращает первую записьВывод:
Если вы хотите, чтобы генерировалось исключение, если результирующий набор содержит много записей, используйте
SingleOrDefault
.Если вам всегда нужна 1 запись, независимо от того, что содержится в наборе результатов, используйте
FirstOrDefault
источник
FirstOrDefault
возвращается первая запись означает новую запись (последнюю) / старую запись (первую)? Вы можете уточнить меня?Там есть
между двумя.
Семантическая разница:
FirstOrDefault
возвращает первый элемент из потенциально нескольких (или по умолчанию, если ни один не существует).SingleOrDefault
Предполагается, что существует один элемент, и возвращает его (или по умолчанию, если его нет). Несколько предметов являются нарушением договора, исключение выдается.Разница в производительности
FirstOrDefault
обычно быстрее, он выполняет итерацию до тех пор, пока не найдет элемент, и должен выполнять итерацию всего перечисляемого, только когда не находит его. Во многих случаях существует высокая вероятность найти предмет.SingleOrDefault
Необходимо проверить, существует ли только один элемент и, следовательно, всегда повторять все перечисляемое. Чтобы быть точным, он повторяется до тех пор, пока не найдет второй элемент и не выдаст исключение. Но в большинстве случаев второго элемента нет.Вывод
Используйте,
FirstOrDefault
если вам все равно, сколько там предметов или когда вы не можете позволить себе проверить уникальность (например, в очень большой коллекции). Когда вы проверяете уникальность при добавлении предметов в коллекцию, может быть слишком дорого проверять это снова при поиске этих предметов.Используйте,
SingleOrDefault
если вам не нужно слишком сильно заботиться о производительности и хотите убедиться, что предположение об одном элементе понятно читателю и проверено во время выполнения.На практике вы используете
First
/FirstOrDefault
часто даже в тех случаях, когда вы принимаете один элемент, для повышения производительности. Вы все равно должны помнить, чтоSingle
/SingleOrDefault
может улучшить читабельность (потому что в нем говорится о единственном элементе) и стабильность (потому что он проверяет его) и использовать его соответствующим образом.источник
SingleOrDefault
при использовании Linq to Objects выполняется итерация по большому количеству объектов, но неSingleOrDefault
нужно ли повторять не более двух элементов, если Linq, например, обращается к базе данных? Просто интересно ..Enumerable
.Никто не упомянул, что FirstOrDefault, переведенный в SQL, делает TOP 1 запись, а SingleOrDefault TOP 2, потому что нужно знать, есть ли более 1 запись.
источник
FirstOrDefault()
добавляет,LIMIT 0,1
покаSingleOrDefault()
ничего не добавляет.Для LINQ -> SQL:
SingleOrDefault
FirstOrDefault
источник
Я использую
SingleOrDefault
в ситуациях, когда моя логика диктует, что будет либо ноль, либо один результат. Если их больше, это ошибочная ситуация, что полезно.источник
SingleOrDefault: вы говорите, что «Максимум» есть один элемент, соответствующий запросу или по умолчанию FirstOrDefault: Вы говорите, что «По крайней мере» один элемент соответствует запросу или по умолчанию
Скажите это вслух в следующий раз, когда вам нужно будет выбрать, и вы, скорее всего, сделаете мудрый выбор. :)
источник
FirstOrDefault. More correctly:
FirstOrDefault` = любое количество результатов, но я забочусь только о первом, результатов также может не быть.SingleOrDefault
= Есть 1 или 0 результатов, если больше, значит, где-то есть ошибка.First
= Есть хотя бы один результат, и я этого хочу.Single
= Есть ровно 1 результат, не больше, не меньше, и я хочу этого.В ваших случаях я бы использовал следующее:
выберите по ID == 5: здесь можно использовать SingleOrDefault, потому что вы ожидаете одну [или ни одну] сущность, если вы получили более одной сущности с идентификатором 5, что-то не так и определенно заслуживает исключения.
при поиске людей, чье имя равно «Бобби», их может быть несколько (вполне возможно, я бы подумал), поэтому вам не следует ни использовать «Одиночный», ни «Первый», просто выберите с помощью операции «Где» (если «Бобби» возвращает слишком много субъекты, пользователь должен уточнить свой поиск или выбрать один из возвращенных результатов)
упорядочение по дате создания также должно выполняться с помощью операции Where (маловероятно, что она будет иметь только одну сущность, сортировка не будет иметь большого значения;) это, однако, подразумевает, что вы хотите отсортировать ВСЕ сущности - если вы хотите просто ОДИН, используйте FirstOrDefault, Одиночный бросил бы каждый раз, если у вас есть более одного лица.
источник
Оба являются операторами элементов, и они используются для выбора одного элемента из последовательности. Но между ними есть небольшая разница. Оператор SingleOrDefault () сгенерирует исключение, если более чем один элемент удовлетворяет условию, когда FirstOrDefault () не сгенерирует ни одного исключения для одного и того же. Вот пример.
источник
В вашем последнем примере:
Да, это так. Если вы попытаетесь использовать,
SingleOrDefault()
и в результате запроса будет больше, чем запись, вы получите и исключение. Единственное время, которое вы можете безопасно использовать,SingleOrDefault()
это когда вы ожидаете только 1 и только 1 результат ...источник
Итак, как я понимаю сейчас,
SingleOrDefault
будет хорошо, если вы запрашиваете данные, которые гарантированно будут уникальными, то есть обеспечены ограничениями БД, такими как первичный ключ.Или есть лучший способ запроса первичного ключа.
Предполагая, что мой TableAcc имеет
и я хочу запросить
AccountNumber 987654
, я используюисточник
По моему мнению,
FirstOrDefault
это слишком злоупотребляют. В большинстве случаев, когда вы фильтруете данные, вы ожидаете получить коллекцию элементов, соответствующих логическому условию, или один уникальный элемент по его уникальному идентификатору, такой как пользователь, книга, публикация и т. Д. почему мы можем даже сказать, чтоFirstOrDefault()
это запах кода не потому, что с ним что-то не так, а потому, что он используется слишком часто. Этот пост в блоге исследует тему в деталях. ИМО в большинстве случаевSingleOrDefault()
является гораздо лучшей альтернативой, поэтому следите за этой ошибкой и убедитесь, что вы используете наиболее подходящий метод, который четко отражает ваш контракт и ожидания.источник
Одна вещь, которая упускается в ответах ....
Если есть несколько результатов, FirstOrDefault без заказа by может вернуть разные результаты, основанные на том, какая серверная стратегия использовалась когда-либо.
Лично я не могу видеть FirstOrDefault в коде, потому что для меня это говорит, что разработчик не заботился о результатах. С заказом, хотя это может быть полезно в качестве способа обеспечения соблюдения самых последних / самых ранних. Мне пришлось исправить много проблем, вызванных небрежными разработчиками, использующими FirstOrDefault.
источник
Я запросил Google для использования различных методов на GitHub. Это делается путем запуска поискового запроса Google для каждого метода и ограничения запроса доменом github.com и расширением файла .cs с помощью запроса "site: github.com file: cs ..."
Похоже, что методы First * используются чаще, чем методы Single *.
источник
Я не понимаю, почему вы используете,
FirstOrDefault(x=> x.ID == key)
когда это может получить результаты гораздо быстрее, если вы используетеFind(key)
. Если вы запрашиваете с помощью первичного ключа таблицы, эмпирическое правило всегда использоватьFind(key)
.FirstOrDefault
следует использовать для таких предикатов и(x=> x.Username == username)
т. д.это не заслуживало отрицательного ответа, поскольку заголовок вопроса не был специфичен для linq на БД или Linq на List / IEnumerable и т. д.
источник
Find()
?