LINQ:
Действительно ли более эффективно использовать Single()
оператор First()
когда когда-нибудь я буду знать наверняка, что запрос возвратит единственную запись?
Существует ли различие?
Я знаю, что другие писали, почему вы используете один или другой, но я подумал, что проиллюстрирую, почему вы НЕ должны использовать один, когда вы имеете в виду другое.
Примечание. В моем коде я обычно использую FirstOrDefault ()
и SingleOrDefault ()
, но это другой вопрос.
Возьмем, к примеру, таблицу, в которой хранятся клиентов
на разных языках с использованием составного ключа ( ID
, Lang
):
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();
Этот код выше вводит возможную логическую ошибку (трудно отследить). Он вернет более одной записи (при условии, что у вас есть запись о клиенте на нескольких языках), но он всегда будет возвращать только первую ... что иногда может работать ... но не другие. Это непредсказуемо.
Поскольку ваше намерение состоит в том, чтобы вернуть Single Customer
, используйте Single ()
;
Следующее вызовет исключение (что вы и хотите в данном случае):
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();
Затем вы просто бьете себя по лбу и говорите себе ... УПС! Я забыл языковое поле! Ниже приводится правильная версия:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();
First ()
полезна в следующем сценарии:
DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();
Он вернет ОДИН объект, и, поскольку вы используете сортировку, это будет самая последняя возвращенная запись.
Использование Single ()
, когда вы чувствуете, что он должен явно всегда возвращать 1 запись, поможет вам избежать логических ошибок.
Многие люди, которых я знаю, используют FirstOrDefault (), но я предпочитаю использовать SingleOrDefault () чаще, потому что, если бы их было больше, часто возникала бы некоторая несогласованность данных. Однако это имеет дело с LINQ-to-Objects.
Если я помню, Single () проверяет, есть ли еще один элемент после первого (и выдает исключение, если это так), а First () прекращается после получения. Оба генерируют исключение, если последовательность пуста.
Лично я всегда использую First ().
Если вы не хотите, чтобы исключение создавалось специально в случае наличия более одного элемента , используйте First ()
.
Оба эффективны, возьмем первый пункт. First ()
немного более эффективен, потому что он не утруждает себя проверкой наличия второго элемента.
Единственное отличие состоит в том, что Single ()
ожидает, что в начале перечисления будет только один элемент, и вызовет исключение, если их больше одного. Вы используете .Single ()
, если хотите, чтобы в этом случае было создано исключение .
Single вызовет исключение, если найдет несколько записей, соответствующих критериям.
Сначала всегда будет выбираться первая запись из списка. Если запрос возвращает только 1 запись, вы можете использовать First ()
.
Оба вызовут исключение InvalidOperationException
, если коллекция пуста.
В качестве альтернативы вы можете использовать SingleOrDefault ()
. Это не вызовет исключения, если список пуст
Между этими двумя методами есть тонкая семантическая разница.
Используйте Single
для извлечения первого (и единственного) элемента из последовательности, которая должна содержать один элемент и не более. Если последовательность содержит более одного элемента, ваш вызов Single
вызовет выдачу исключения, поскольку вы указали, что должен быть только один элемент.
Используйте Сначала
, чтобы извлечь первый элемент из последовательности, которая может содержать любое количество элементов. Если в последовательности больше одного элемента, ваш вызов First
не вызовет выброса исключения, поскольку вы указали, что вам нужен только первый элемент в последовательности, и не заботитесь о том, существуют ли другие элементы.
Если последовательность не содержит элементов, оба вызова методов вызовут исключение, поскольку оба метода ожидают присутствия хотя бы одного элемента.
Они разные. Оба они утверждают, что набор результатов не пустой, но одиночный также утверждает, что существует не более 1 результата. Я лично использую Single в тех случаях, когда я ожидаю, что будет только 1 результат только потому, что получение более одного результата является ошибкой и, вероятно, должно рассматриваться как таковое.