Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
Первый тест (из CarTests.cs) просто подсчитывает все записи Car в базе данных. Из-за того, что фильтр запросов активен, результатом подсчета будет 9:
[Fact]
public void ShouldGetTheCountOfCars()
{
var count = Context.Cars.Count();
Assert.Equal(9, count);
}
Ниже приведен код SQL, который выполнялся:
The executed SQL is shown here:SELECT COUNT(*)
FROM [dbo].[Inventory] AS [i]
WHERE [i].[IsDrivable] = CAST(1 AS bit)
После добавления вызова IgnoreQueryFilters() метод Count() возвращает 10 и конструкция WHERE удаляется из запроса SQL:
[Fact]
public void ShouldGetTheCountOfCarsIgnoreQueryFilters()
{
var count = Context.Cars.IgnoreQueryFilters().Count();
Assert.Equal(10, count);
}
Вот сгенерированный код SQL:
SELECT COUNT(*) FROM [dbo].[Inventory] AS [i]
Следующие тесты (из CarTests.cs) демонстрируют метод Count() с условием WHERE. В первом тесте выражение добавляется прямо в вызов метода Count(), а во втором вызов метода Count() помещается в конец запроса LINQ:
[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 следующий тест:
[Theory]
[InlineData(1, "Zippy")]
[InlineData(2, "Rusty")]
[InlineData(3, "Mel")]
[InlineData(4, "Clunker")]
[InlineData(5, "Bimmer")]
[InlineData(6, "Hank")]
[InlineData(7, "Pinky")]
[InlineData(8, "Pete")]
[InlineData(9, "Brownie")]
public void ShouldGetValueFromStoredProc(int id, string expectedName)
{
Assert.Equal(expectedName, new CarRepo(Context).GetPetName(id));
}
Создание записей
Записи добавляются в базу данных за счет их создания в коде, добавления к DbSet<T> и вызова метода SaveChanges()/SaveChangesAsync() контекста. Во время выполнения метода SaveChanges() объект ChangeTracker сообщает обо всех добавленных сущностях, а инфраструктура EF Core вместе с поставщиком баз данных создают подходящий оператор (операторы) SQL для вставки записи (записей).
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Татьяна24 сентябрь 22:20 Как то не очень... Невеста по ошибке. Я не дам тебе развод - Майя Линн
-
Римма24 сентябрь 21:52 Почему главные героинитпкие идиотки? И сюжет не плохой, и написано хорошо. Но как героиня - так дура дурой.... Хозяйка маленького дома, или Любимая для дракона - Кира Рамис
-
Римма20 сентябрь 12:27 Много ненужных пояснений и отступлений. Весь сюжет теряет свою привлекательность. Героиня иногда так тупит, что читать не... Хозяйка приюта для перевертышей и полукровок - Елена Кутукова