Язык программирования C#9 и платформа .NET5
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=6Any() и All()
Методы
иAny()проверяют набор записей, чтобы выяснить, соответствует ли критериям любая запись (All()) или же все записи (Any()). Как и вызовы методов агрегирования, их можно добавлять в конец запроса LINQ с вызовамиАll()либо же помещать выражение фильтрации в сам вызов метода. МетодыWhere()иAny()выполняются на серверной стороне, а из запроса возвращается булевское значение. Глобальные фильтры запросов оказывают воздействие на методыAll()иAny(); их можно отключить с помощьюAll().IgnoreQueryFilters()Все операторы SQL, показанные в этом разделе, были получены с применением профилировщика SQL Server. Первый тест (из
) проверяет, имеет ли любая запись Car специфическое значениеCarTests.cs: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);}Для первого теста
выполняется следующий код SQL:[Theory]exec sp_executesql N'SELECT CASEWHEN EXISTS (SELECT 1FROM [dbo].[Inventory] AS [i]WHERE ([i].[IsDrivable] = CAST(1 AS bit))AND ([i].[MakeId] = @__makeId_0)) THENCAST(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 CASEWHEN NOT EXISTS (SELECT 1FROM [dbo].[Inventory] AS [i]WHERE ([i].[IsDrivable] = CAST(1 AS bit))AND ([i].[MakeId] <> @__makeId_0)) THENCAST(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")]