exec sp_executesql N'SELECT COUNT(*)
FROM [dbo].[Inventory] AS [i]
WHERE ([i].[IsDrivable] = CAST(1 AS bit)) AND ([i].[MakeId] = @__makeId_0)'
,N'@__makeId_0 int',@__makeId_0=6
Any() и All()
Методы
Any()
и
All()
проверяют набор записей, чтобы выяснить, соответствует ли критериям любая запись (
Any()
) или же все записи (
Аll()
). Как и вызовы методов агрегирования, их можно добавлять в конец запроса LINQ с вызовами
Where()
либо же помещать выражение фильтрации в сам вызов метода. Методы
Any()
и
All()
выполняются на серверной стороне, а из запроса возвращается булевское значение. Глобальные фильтры запросов оказывают воздействие на методы
Any()
и
All()
; их можно отключить с помощью
IgnoreQueryFilters()
.
Все операторы SQL, показанные в этом разделе, были получены с применением профилировщика SQL Server. Первый тест (из
CarTests.cs
) проверяет, имеет ли любая запись Car специфическое значение
MakeId
:
[Theory]
[InlineData(1, true)]
[InlineData(11, false)]
public void ShouldCheckForAnyCarsWithMake(int makeId, bool expectedResult)
{
var result = Context.Cars.Any(x => x.MakeId == makeId);
Assert.Equal(expectedResult, result);
}
Для первого теста
[Theory]
выполняется следующий код SQL:
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [dbo].[Inventory] AS [i]
WHERE ([i].[IsDrivable] = CAST(1 AS bit))
AND ([i].[MakeId] = @__makeId_0)) THEN
CAST(1 AS bit)
ELSE CAST(0 AS bit)
END',N'@__makeId_0 int',@__makeId_0=1
Второй тест проверяет, имеют ли все записи
Car
специфическое значение
MakeId
:
[Theory]
[InlineData(1, false)]
[InlineData(11, false)]
public void ShouldCheckForAllCarsWithMake(int makeId, bool expectedResult)
{
var result = Context.Cars.All(x => x.MakeId == makeId);
Assert.Equal(expectedResult, result);
}
Вот код SQL, выполняемый для второго теста
[Theory]
:
exec sp_executesql N'SELECT CASE
WHEN NOT EXISTS (
SELECT 1
FROM [dbo].[Inventory] AS [i]
WHERE ([i].[IsDrivable] = CAST(1 AS bit))
AND ([i].[MakeId] <> @__makeId_0)) THEN
CAST(1 AS bit)
ELSE CAST(0 AS bit)
END',N'@__makeId_0 int',@__makeId_0=1
Получение данных из хранимых процедур
Последний шаблон извлечения данных, который необходимо изучить, предусматривает получение данных из хранимых процедур. Несмотря на некоторые пробелы EF Core в плане работы с хранимыми процедурами (по сравнению с EF 6), не забывайте, что инфраструктура EF Core построена поверх ADO.NET. Нужно просто спуститься на уровень ниже и вспомнить, как вызывались хранимые процедуры до появления инструментов объектно-реляционного отображения. Показанный далее метод в
CarRepo
создает обязательные параметры (входной и выходной), задействует свойство
Database
экземпляра
ApplicationDbContext
и вызывает
ExecuteSqlRaw()
:
public string GetPetName(int id)
{
var parameterId = new SqlParameter
{
ParameterName = "@carId",
SqlDbType = System.Data.SqlDbType.Int,
Value = id,
};
var parameterName = new SqlParameter
{
ParameterName = "@petName",
SqlDbType = System.Data.SqlDbType.NVarChar,
Size = 50,
Direction = ParameterDirection.Output
};
var result = Context.Database
.ExecuteSqlRaw("EXEC [dbo].[GetPetName] @carId, @petName OUTPUT",
parameterId,
parameterName);
return (string)parameterName.Value;
}
При наличии такого кода тест становится тривиальным. Добавьте в файл класса
CarTests.cs
следующий тест:
[Theory]
[InlineData(1, "Zippy")]
[InlineData(2, "Rusty")]
[InlineData(3, "Mel")]