【发布时间】:2018-07-20 15:36:24
【问题描述】:
当通过实体框架数据库上下文更新数据库中的多条记录时,一条记录会引发乐观并发异常,并且该记录不会在数据库中更新。但我发现其他更新的记录被保存到数据库中。乐观并发异常是否不应该回滚在乐观并发异常之前所做的所有更改?
【问题讨论】:
标签: entity-framework
当通过实体框架数据库上下文更新数据库中的多条记录时,一条记录会引发乐观并发异常,并且该记录不会在数据库中更新。但我发现其他更新的记录被保存到数据库中。乐观并发异常是否不应该回滚在乐观并发异常之前所做的所有更改?
【问题讨论】:
标签: entity-framework
我敢打赌,每当需要更新时,EF 库都会抛出异常,但 SQL Server 响应表明没有进行任何更新。
当预期实体的 SaveChanges 会导致数据库更新但实际上数据库中没有任何行受到影响时,由 DbContext 引发异常。这通常表明数据库已同时更新,因此预期匹配的并发令牌实际上并不匹配。请注意,此异常引用的状态条目出于安全原因不会序列化,序列化后对状态条目的访问将返回 null。
Entity Framework 也可以转换为每个对象的单个 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();
}
}
相关阅读:
更多关于DbUpdateConcurrencyException Class
更多关于Update Data in Disconnected Scenario in Entity Framework Core(更新多个实体)
【讨论】: