Язык программирования C#9 и платформа .NET5
• Метод
возвращает первую запись, которая соответствует условию запроса и любым конструкциям упорядочения. Если конструкции упорядочения не указаны, то возвращаемая запись основывается на порядке, установленном в базе данных. Если запросу не соответствует одна или большее число записей, тогда генерируется исключение.Single()• Поведение метода
совпадает с поведениемSingleOrDefault(), но при отсутствии записей, соответствующих запросу,Single()возвращает стандартное значение для типа (SingleOrDefault()).null• Метод
возвращает последнюю запись, которая соответствует условию запроса и любым конструкциям упорядочения. Если конструкции упорядочения не указаны, то возвращаемая запись основывается на порядке, установленном в базе данных. Если запись не возвращается, тогда генерируется исключение.Last()• Поведение метода
совпадает с поведениемLastOrDefault(), но при отсутствии записей, соответствующих запросу,Last()возвращает стандартное значение для типа (LastOrDefault()).nullВсе методы могут также принимать
(лямбда-выражение) для фильтрации результирующего набора. Это означает, что вы можете помещать выражениеExpression<Func<T, bool>>внутрь вызоваWhere(). Следующие операторы эквивалентны:First()/Single()Context.Customers.Where(c=>c.Id < 5).First();Context.Customers.First(c=>c.Id < 5);Из-за немедленного выполнения операторов LINQ, извлекающих одиночную запись, метод
оказывается недоступным. Приводимые трансляции запросов в код SQL получены с применением профилировщика SQL Server.ToQueryString()Использование First()/FirstOrDefault()
При использовании формы
иFirst()без параметров будет возвращаться первая запись (на основе порядка в базе данных или предшествующих конструкций упорядочения).FirstOrDefault()Показанный далее тест получает первую запись на основе порядка в базе данных:
[Fact]public void GetFirstMatchingRecordDatabaseOrder(){// Получить первую запись на основе порядка в базе данных.<b> var customer = Context.Customers.First();</b>Assert.Equal(1, customer.Id);}Предыдущий запрос LINQ транслируется в такой код SQL:
SELECT TOP(1) [c].[Id], [c].[TimeStamp], [c].[FirstName], [c].[FullName],[c].[LastName]FROM [Dbo].[Customers] AS [c]Следующий тест получает первую запись на основе порядка "фамилия, имя":
[Fact]public void GetFirstMatchingRecordNameOrder(){// Получить первую запись на основе порядка "фамилия, имя".var customer = Context.Customers<b> .OrderBy(x => x.PersonalInformation.LastName)</b><b> .ThenBy(x => x.PersonalInformation.FirstName)</b><b> .First();</b>Assert.Equal(1, customer.Id);}Предыдущий запрос LINQ транслируется в такой код SQL:
SELECT TOP(1) [c].[Id], [c].[TimeStamp], [c].[FirstName], [c].[FullName],[c].[LastName]FROM [Dbo].[Customers] AS [c]ORDER BY [c].[LastName], [c].[FirstName]Приведенный ниже тест выдвигает утверждение о том, что если для
не найдено соответствие, тогда генерируется исключение:First()[Fact]public void FirstShouldThrowExceptionIfNoneMatch(){// Фильтровать на основе Id.// Сгенерировать исключение, если соответствие не найдено.<b> Assert.Throws<InvalidOperationException>(()</b><b> => Context.Customers.First(x => x.Id == 10));</b>}Предыдущий запрос LINQ транслируется в такой код SQL:
SELECT TOP(1) [c].[Id], [c].[TimeStamp], [c].[FirstName], [c].[FullName],[c].[LastName]FROM [Dbo].[Customers] AS [c]WHERE [c].[Id] = 10На заметку!
— это специальный тип утверждения, который ожидает, что код в выражении сгенерирует исключение. Если исключение не было сгенерировано, тогда утверждение терпит неудачу.Assert.Throws()В случае применения метода
, если соответствие не найдено, то результатом будет null, а не исключение:FirstOrDefault()[Fact]public void FirstOrDefaultShouldReturnDefaultIfNoneMatch(){// Expression<Func<Customer>> - это лямбда-выражение.Expression<Func<Customer, bool>> expression = x => x.Id == 10;// Возвращает null, если ничего не найдено.<b> var customer = Context.Customers.FirstOrDefault(expression);</b>Assert.Null(customer);