调用AddDataProtection().PersistKeysToDbContext插入行时遇并发异常如何解决?
解决AddDataProtection持久化密钥时的DbUpdateConcurrencyException异常
异常信息
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded
可能原因及解决方法
1. 实体模型缺少并发令牌配置
DataProtection更新密钥时依赖EF Core的并发检测,默认DataProtectionKey实体需配置并发令牌处理冲突。修改ProtectionKeyContext的OnModelCreating方法,为Xml字段添加并发令牌:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<DataProtectionKey>(entity => { entity.ToTable("DataProtectionKeys"); entity.HasKey(e => e.Id); entity.Property(e => e.FriendlyName).HasMaxLength(255); // 添加并发令牌配置 entity.Property(e => e.Xml).IsRequired().IsConcurrencyToken(); }); }
2. 数据库表结构与实体模型不匹配
确保DataProtectionKeys表结构和实体配置完全一致:
- 确认
Id为字符串类型主键(DataProtectionKey的Id默认是字符串) - 确认
Xml字段为非空大文本类型(如SQL Server的NVARCHAR(MAX)),避免长度不足 - 执行EF Core迁移或手动同步表结构,消除字段缺失、类型不匹配问题
3. 多实例并发写入冲突
多应用实例部署时,可能出现同时创建/更新密钥的并发冲突。为EF Core添加重试策略处理瞬时异常:
builder.Services.AddDbContext<ProtectionKeyContext>(options => options.UseSqlServer("connection-string", sqlOptions => sqlOptions.EnableRetryOnFailure()));
4. DbContext生命周期问题
保持ProtectionKeyContext使用默认的Scoped生命周期(AddDbContext默认配置),禁止使用Singleton生命周期,避免上下文状态混乱引发数据跟踪异常。
5. 外部进程修改数据库数据
排查是否有其他进程(手动操作、第三方服务)修改/删除了DataProtectionKeys表数据,导致EF Core跟踪的实体与数据库实际数据不一致。
内容的提问来源于stack exchange,提问作者CircuitSquirrel7812
相关产品推荐
相关产品推荐

