更新了多个记录的实体框架乐观并发异常



通过实体框架数据库上下文更新数据库中的多条记录时,一条记录引发乐观并发异常,该记录不会在数据库中更新。但我发现其他更新的记录被持久化到数据库中。乐观并发异常是否应该回滚在乐观并发异常之前所做的所有更改?

我敢打赌,无论何时需要更新,EF库都会抛出异常,但SQL Server响应表明没有进行任何更新。

当预期实体的SaveChanges将导致数据库更新,但实际上数据库中没有行受到影响时,DbContext引发异常。这通常表示数据库已被并发更新,因此预期匹配的并发令牌实际上并不匹配。请注意,由于安全原因,此异常引用的状态条目未序列化,并且序列化后对状态条目的访问将返回null。

此外,实体框架还可以转换为每个对象的单个SQL UPDATE语句,例如

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Students] SET [Name] = @p0
WHERE [StudentId] = @p1;
SELECT @@ROWCOUNT;
UPDATE [Students] SET [Name] = @p2
WHERE [StudentId] = @p3;
SELECT @@ROWCOUNT;
UPDATE [Students] SET [Name] = @p4
WHERE [StudentId] = @p5;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000),@p3 int,@p2 nvarchar(4000),@p5 int,@p4 
nvarchar(4000)',
@p1=1,@p0=N'Bill',@p3=2,@p2=N'Steve',@p5=3,@p4=N'James'
go

这意味着SQL Server一切正常,事务由实体框架提交。只有EF抛出异常,让您知道出了问题。在您的情况下,其中一条语句不更新任何内容,并且更新的行数为0。

如果在这样的更新过程中需要回滚所有更改,则必须用另一个事务封装它。根据需要提交和回滚。

using (var dbContextTransaction = context.Database.BeginTransaction()) 
{ 
try 
{ 
// Do your stuff
context.SaveChanges(); 
dbContextTransaction.Commit(); 
} 
catch (DbUpdateConcurrencyException) 
{ 
// Expected
dbContextTransaction.Rollback(); 
}
catch (Exception)
{
// Unexpected
dbContextTransaction.Rollback();
}
}

相关读数:

有关DbUpdateConcurrentException类的更多信息

更多关于实体框架核心(更新多个实体(中断开连接场景中的更新数据

更多关于使用事务的实体框架

最新更新