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

ЖАНРЫ

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

[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 для вставки записи (записей).

Вспомните, что метод

SaveChanges
выполняется в неявной транзакции, если только не применяется явная транзакция. Если сохранение было успешным, то затем запрашиваются значения, сгенерированные сервером, для установки значений в сущностях. Все эти тесты будут использовать явную транзакцию, так что можно производить откат, оставив базу данных в том же состоянии, в каком она находилась, когда начинался прогон тестов.

Все операторы SQL, показанные далее в разделе, были получены с применением профилировщика SQL Server.

На заметку! Записи можно добавлять также с использованием класса, производного от

DbContext
. Во всех примерах для добавления записей будут применяться свойства
DbSet<T>
. В классах
DbSet<T>
и
DbContext
имеются асинхронные версии методов
Add/AddRange
, но здесь рассматриваются только синхронные версии.

Состояние сущности

Когда сущность создана с помощью кода, но еще не была добавлена в

DbSet<T>
, значением
EntityState
является
Detached
. После добавления новой сущности в
DbSet<T>
значение
EntityState
устанавливается в
Added
. В случае успешного выполнения
SaveChanges
значение
EntityState
устанавливается в
Unchanged
.

Добавление одной записи

В следующем тесте демонстрируется добавление одиночной записи в таблицу

Inventory
:

[Fact]

public void ShouldAddACar

{

ExecuteInATransaction(RunTheTest);

void RunTheTest

{

var car = new Car

{

Color = "Yellow",

MakeId = 1,

PetName = "Herbie"

};

var carCount = Context.Cars.Count;

Context.Cars.Add(car);

Context.SaveChanges;

var newCarCount = Context.Cars.Count;

Assert.Equal(carCount+1,newCarCount);

}

}

Ниже приведен

выполняемый оператор SQL. Обратите внимание, что у недавно добавленной сущности запрашиваются свойства, сгенерированные базой данных (
Id
и
TimeStamp
). Когда результат запроса поступает в исполняющую среду EF Core, сущность обновляется с использованием значений серверной стороны:

exec sp_executesql N'SET NOCOUNT ON;

INSERT INTO [dbo].[Inventory] ([Color], [MakeId], [PetName])

VALUES (@p0, @p1, @p2);

SELECT [Id], [IsDrivable], [TimeStamp]

FROM [dbo].[Inventory]

WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity;

',N'@p0 nvarchar(50),@p1 int,@p2 nvarchar(50)',@p0=N'Yellow',@p1=1,@p2=N'Herbie'

Добавление одной записи с использованием метода Attach

Когда первичный ключ сущности сопоставлен со столбцом идентичности в SQL Server, исполняющая среда EF Core будет трактовать экземпляр сущности как добавленный (

Added
), если значение свойства первичного ключа равно 0. Следующий тест создает новую сущность
Car
и оставляет для свойства
Id
стандартное значение 0. После присоединения сущности к
ChangeTracker
ее состояние устанавливается в
Added
и вызов
SaveChanges
добавит сущность в базу данных:

[Fact]

public void ShouldAddACarWithAttach

{

ExecuteInATransaction(RunTheTest);

void RunTheTest

{

var car = new Car

{

Color = "Yellow",

MakeId = 1,

PetName = "Herbie"

};

var carCount = Context.Cars.Count;

Context.Cars.Attach(car);

Assert.Equal(EntityState.Added, Context.Entry(car).State);

Context.SaveChanges;

var newCarCount = Context.Cars.Count;

Assert.Equal(carCount + 1, newCarCount);

}

}

Добавление нескольких записей одновременно

Чтобы вставить в одной транзакции сразу несколько записей, применяйте метод

AddRange
класса
DbSet<T>
, как показано в приведенном далее тесте (обратите внимание, что для активизации пакетирования при сохранении данных в SQL Server должно быть инициировано не менее четырех действий):

[Fact]

public void ShouldAddMultipleCars

{

ExecuteInATransaction(RunTheTest);

void RunTheTest

{

// Для активизации пакетирования должны быть добавлены четыре сущности

var cars = new List<Car>

{

new { Color = "Yellow", MakeId = 1, PetName = "Herbie" },

new { Color = "White", MakeId = 2, PetName = "Mach 5" },

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