Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

[Theory]

[InlineData(1, 1)]

[InlineData(2, 1)]

[InlineData(3, 1)]

[InlineData(4, 2)]

[InlineData(5, 3)]

[InlineData(6, 1)]

public void ShouldGetTheCountOfCarsByMakeP1(int makeId, int expectedCount)

{

var count = Context.Cars.Count(x=>x.MakeId == makeId);

Assert.Equal(expectedCount, count);

}

[Theory]

[InlineData(1, 1)]

[InlineData(2, 1)]

[InlineData(3, 1)]

[InlineData(4, 2)]

[InlineData(5, 3)]

[InlineData(6, 1)]

public void ShouldGetTheCountOfCarsByMakeP2(int makeId, int expectedCount)

{

var count = Context.Cars.Where(x => x.MakeId == makeId).Count;

Assert.Equal(expectedCount, count);

}

Оба

теста создают те же самые обращения SQL к серверу (в каждом тесте значение для
MakeId
изменяется на основе
[InlineData]
):

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
следующий тест:

Поделиться с друзьями: