.NET 8中EF插入ProcessingFlags表触发Identity列插入异常
解决方法
方案1:移除Id列的IDENTITY属性
既然需要手动插入枚举值作为Id,直接去掉数据库中ProcessingFlags表Id列的IDENTITY(1,1)属性:
- 在
ProcessingFlagsConfiguration中配置Id为手动赋值:
public class ProcessingFlagsConfiguration : IEntityTypeConfiguration<JobRunning> { public void Configure(EntityTypeBuilder<JobRunning> builder) { builder.HasKey(e => e.Id); // 明确指定Id由用户提供,而非数据库生成 builder.Property(e => e.Id).ValueGeneratedNever(); } }
- 生成新的迁移:
Add-Migration RemoveProcessingFlagsIdIdentity
- 执行迁移更新数据库:
Update-Database
这样数据库的Id列不再是自增列,外部库设置的枚举值就能正常插入。
方案2:保留IDENTITY属性,插入时临时开启IDENTITY_INSERT
如果必须保留Id列的IDENTITY属性,可以通过EF Core的拦截器在插入JobRunning实体时自动开启IDENTITY_INSERT:
- 创建一个拦截器类:
public class ProcessingFlagsIdentityInsertInterceptor : SaveChangesInterceptor { public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result) { var context = eventData.Context; if (context == null) return result; // 检查是否有JobRunning实体需要插入 var pendingInserts = context.ChangeTracker.Entries<JobRunning>() .Where(e => e.State == EntityState.Added); if (pendingInserts.Any()) { // 开启IDENTITY_INSERT context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT ProcessingFlags ON"); // 执行保存后关闭IDENTITY_INSERT context.SaveChangesCompleted += (s, e) => { context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT ProcessingFlags OFF"); }; } return result; } }
- 在DbContext中注册拦截器:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.AddInterceptors(new ProcessingFlagsIdentityInsertInterceptor()); }
- 无需修改现有迁移,直接运行程序即可。外部库设置的枚举Id会被正常插入,插入完成后IDENTITY_INSERT自动关闭。
为什么ValueGeneratedOnAdd无效?
ValueGeneratedOnAdd的作用是告诉EF:当实体的Id为默认值(比如int类型的0)时,由数据库生成值。但外部库会主动给Id赋值为枚举值(非默认值),此时EF会认为需要将这个值插入到数据库,而数据库的IDENTITY列不允许手动插入值(除非IDENTITY_INSERT开启),所以依然会报错。
内容的提问来源于stack exchange,提问作者Diego Perez
相关产品推荐
相关产品推荐

