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);
}
}
В предыдущем коде задействована транзакция, совместно используемая двумя экземплярами ApplicationDbContext
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [dbo].[Inventory] SET [Color] = @p0
WHERE [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, который устанавливает состояние в Modified:context2.Cars.Update(updatedCar);
Второй способ связан с применением экземпляра контекста и метода Entry()
Modified:context2.Entry(updatedCar).State = EntityState.Modified;
В любом случае для сохранения значений все равно должен вызываться метод SaveChanges()
В представленном далее тесте читается неотслеживаемая запись, из нее создается новый экземпляр класса Car
Color). Затем в зависимости от того, с какой строки кода вы уберете комментарий, либо устанавливается состояние, либо использует метод Update() на DbSet. Метод Update() также изменяет состояние на Modified. Затем в тесте вызывается метод SaveChanges(). Все дополнительные контексты нужны для обеспечения точности теста и отсутствия пересечения между контекстами:[Fact]
public void ShouldUpdateACarUsingState()
{
ExecuteInASharedTransaction(RunTheTest);
void RunTheTest(IDbContextTransaction trans)
{
var car = Context.Cars.AsNoTracking().First(c => c.Id == 1);
Assert.Equal("Black", car.Color);
var updatedCar = new Car
{
Color = "White", //Original is Black
Id = car.Id,
MakeId = car.MakeId,
PetName = car.PetName,
TimeStamp = car.TimeStamp
IsDrivable = car.IsDrivable
};
var context2 = TestHelpers.GetSecondContext(Context, trans);
// Либо вызвать Update(), либо модифицировать состояние.
context2.Entry(updatedCar).State = EntityState.Modified;
// context2.Cars.Update(updatedCar);
context2.SaveChanges();
var context3 =
TestHelpers.GetSecondContext(Context, trans);