Стандартные операторы запроса с LINQ - First и Single

ОГЛАВЛЕНИЕ

First и Single

Если нужно выбрать в последовательности одно значение, удобно применять операторы First, FirstOrDefault, Single и SingleOrDefault. Метод First возвращает первый элемент последовательность. В него можно передать лямбда-выражение, задающее определенные условия. Например, если нужно в последовательности целых чисел найти первое значение, превышающее 50, можно использовать следующий код:

int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
int num1 = nums.First<int>();
int num2 = nums.First<int>(x => x > 50);
int num3 = nums.FirstOrDefault<int>(x => x > 5000);

Console.WriteLine(
  num1.ToString() + "-" + 
  num2.ToString() + "-" + 
  num3.ToString());

Это фрагмент кода возвращает первый элемент (1), первый элемент, превышающий 50, (64) и первый элемент, превышающий 5000. Поскольку элемента, удовлетворяющего третьему условию, нет (в последовательности нет чисел больше 5000), то в случае использования оператора First (а не FirstOrDefault) выдается исключение. При использовании оператора FirstOrDefault, если нет элементов, удовлетворяющих условиям лямбда-выражения, код возвращает 0. Оператор First можно также использовать в запросах типа «LINQ — сущности»:

using (Entities entities = new Entities())
{
  var query = (from c in entities.Customers
  select c).First(c => c.City.Equals("London"));
  Console.WriteLine(query.CompanyName);

В данном примере фрагмент кода возвращает имя первого клиента лондонского офиса компании. Как мы видим, в разных поставщиках LINQ («LINQ — объекты» и «LINQ — сущности» в нашем случае) используется один и тот же синтаксис.

Оператор First удобно применять в контексте «LINQ — сущности», особенно если заранее известно, что запрос вернет только одну запись. Например, можно создать запрос, который будет находить клиента по идентификатору. В таком случае запрос может вернуть либо одну запись, либо ни одной, и здесь последовательность немногим полезнее самой сущности. Другими словами, можно использовать саму сущность Customer, а не последовательность, состоящую из 1 сущности. Это один из тех случаев, в которых метод First приходится кстати (см. фрагмент кода, приведенный ниже). Поскольку Entity Framework даже не пытается распределить выполнение одного запроса между клиентом и сервером, метод Single в методе «LINQ — сущности» не поддерживается — используется метод First.

using (Entities entities = new Entities())
{
  var query = (from c in entities.Customers
  where c.CustomerID.Equals("BOLID")
  select c).First();
  Console.WriteLine(query.CompanyName);