Язык программирования C#9 и платформа .NET5
Context.Makes.Add(make);var carCount = Context.Cars.Count();var makeCount = Context.Makes.Count();Context.SaveChanges();var newCarCount = Context.Cars. Count();var newMakeCount = Context.Makes. Count();Assert.Equal(carCount+1,newCarCount);Assert.Equal(makeCount+1,newMakeCount);}}Операторы добавления не пакетируются из-за наличия менее двух операторов, а в SQL Server пакетирование начинается с четырех операторов. Ниже показаны выполняемые операторы SQL:
exec sp_executesql N'SET NOCOUNT ON;INSERT INTO [dbo].[Makes] ([Name])VALUES (@p0);SELECT [Id], [TimeStamp]FROM [dbo].[Makes]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();',N'@p0 nvarchar(50)',@p0=N'Honda'exec sp_executesql N'SET NOCOUNT ON;INSERT INTO [dbo].[Inventory] ([Color], [MakeId], [PetName])VALUES (@p1, @p2, @p3);SELECT [Id], [IsDrivable], [TimeStamp]FROM [dbo].[Inventory]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();',N'@p1 nvarchar(50),@p2 int,@p3 nvarchar(50)',@p1=N'Yellow',@p2=7,@p3=N'Herbie'Обновление записей
Записи обновляются за счет их загрузки в
как отслеживаемой сущности, их изменения посредством кода и вызова методаDbSet<T>контекста. При выполненииSaveChanges()объектSaveChanges()сообщает обо всех модифицированных сущностях и исполняющая среда EF Core (наряду с поставщиком баз данных) создает надлежащий оператор SQL для обновления записи (или операторы SQL, если записей несколько).ChangeTrackerСостояние сущности
Когда сущность редактируется,
устанавливается вEntityState. После успешного сохранения изменений состояние возвращается кModified.UnchangedОбновление отслеживаемых сущностей
Обновление одиночной записи очень похоже на добавление одной записи. Вам понадобится загрузить запись из базы данных, внести в нее какие-то изменения и вызвать метод
. Обратите внимание, что вам не нужно вызыватьSaveChanges()на экземпляреUpdate()/UpdateRange(), поскольку сущности отслеживаются. Представленный ниже тест обновляет только одну запись, но при обновлении и сохранении множества отслеживаемых сущностей процесс будет таким же:DbSet<T>[Fact]public void ShouldUpdateACar(){ExecuteInASharedTransaction(RunTheTest);void RunTheTest(IDbContextTransaction trans){var car = Context.Cars.First(c => c.Id == 1);Assert.Equal("Black",car.Color);car.Color = "White";// Вызывать Update() не нужно, т.к. сущность отслеживается.// Context.Cars.Update(car);Context.SaveChanges();Assert.Equal("White", car.Color);var context2 = TestHelpers.GetSecondContext(Context, trans);var car2 = context2.Cars.First(c => c.Id == 1);Assert.Equal("White", car2.Color);}}В предыдущем коде задействована транзакция, совместно используемая двумя экземплярами
. Это должно обеспечить изоляцию между контекстом, выполняющим тест, и контекстом, проверяющим результат теста. Вот выполняемый оператор SQL:ApplicationDbContextexec sp_executesql N'SET NOCOUNT ON;UPDATE [dbo].[Inventory] SET [Color] = @p0WHERE [Id] = @p1 AND [TimeStamp] = @p2;SELECT [TimeStamp]FROM [dbo].[Inventory]WHERE @@ROWCOUNT = 1 AND [Id] = @p1;',N'@p1 int,@p0 nvarchar(50),@p2 varbinary(8)',@p1=1,@p0=N'White',@p2=0x000000000000862DНа заметку! В показанной выше конструкции
проверяется не только столбецWHERE, но и столбецId. Проверка параллелизма будет раскрыта очень скоро .TimeStampОбновление неотслеживаемых сущностей
Неотслеживаемые сущности тоже можно использовать для обновления записей базы данных. Процесс аналогичен обновлению отслеживаемых сущностей за исключением того, что сущность создается в коде (и не запрашивается), а исполняющую среду EF Core потребуется уведомить о том, что сущность уже должна существовать в базе данных и нуждается в обновлении.
После создания экземпляра сущности есть два способа уведомления EF Core о том, что эту сущность необходимо обработать как обновление. Первый способ предусматривает вызов метода
на экземпляреUpdate(), который устанавливает состояние вDbSet<T>:Modifiedcontext2.Cars.Update(updatedCar);Второй способ связан с применением экземпляра контекста и метода
для установки состояния вEntry():Modified