IDENTITY_INSERT设为OFF时无法插入Customers表标识列的问题
看起来你遇到了一个挺棘手的间歇性问题——每天固定时间添加Customer时触发IDENTITY_INSERT错误,重启能解决但次日复发。我来帮你梳理下可能的根因和可行的解决办法:
错误核心分析
这个错误的本质是:EF Core在插入新Customer时,试图给数据库自增的Id列赋显式值,但此时表的IDENTITY_INSERT处于关闭状态。正常情况下,EF应该知道Id是数据库自动生成的,不会尝试赋值。间歇性出现说明不是代码逻辑的永久问题,而是运行时的状态异常导致的。
可能的原因及排查步骤
1. DbContext生命周期配置错误
ASP.NET Core中DbContext默认是Scoped生命周期(每个请求创建一个实例),如果你的项目中错误地把它注册成了Singleton或者Transient,会导致DbContext长期持有、状态混乱,尤其在多线程环境下,元数据缓存可能被篡改,让EF误以为需要给Id赋值。
检查修复:
在Startup.cs中确认DbContext的注册方式:
services.AddDbContext<YourDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("YourConnString")));
确保没有手动指定ServiceLifetime.Singleton或Transient,保持默认的Scoped即可。
2. EF Core模型配置不明确
虽然你尝试过ValueGeneratedOnAdd,但旧版本EF Core 1.1对模型配置的兼容性和稳定性较差,可能出现配置失效的情况。需要明确强制Id为自增列。
两种修复方式:
- 实体类直接标注(更直观):
public class Customer { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } // 其他属性... }
- OnModelCreating中配置:
modelBuilder.Entity<Customer>() .Property(c => c.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
这样能明确告诉EF:Id由数据库自动生成,永远不要尝试给它赋显式值。
3. AutoMapper映射规则异常
你用AutoMapper在Models.Customer和Infrastructure.Customer之间转换,有可能映射规则意外把源对象的Id(哪怕是默认值0)传递给了目标实体,或者缓存了错误的映射逻辑,导致EF误判。
修复:
显式配置AutoMapper忽略Id字段,确保目标实体的Id始终由数据库生成:
CreateMap<Models.Customer, Infrastructure.Customer>() .ForMember(dest => dest.Id, opt => opt.Ignore());
4. 定时任务/高并发触发的状态异常
错误每天同一时间出现,大概率和定时任务(比如Azure WebJobs、定时API)或固定时段的高并发请求有关。比如某个任务可能临时修改了EF的模型状态,或者触发了旧版本EF的并发bug。
排查:
- 检查该时段是否有批量操作、数据同步类任务在运行;
- 查看应用日志,确认错误发生时的请求量和任务执行情况。
5. 升级EF Core版本(最关键的彻底修复)
你使用的EF Core 1.1是非常老旧的版本,早已停止官方支持,存在大量已知的元数据缓存、并发状态相关的bug。升级到更高版本(至少EF Core 2.2,推荐直接升级到.NET 6/7 LTS版本),能从根源上解决这类间歇性稳定性问题。
临时应急方案
如果暂时无法升级版本,可以在代码中捕获该异常并重试,同时记录日志便于排查:
public Models.Customer Create(Models.Customer customer) { try { var dm = Mapper.Map<Infrastructure.Customer>(customer); _logger.LogInformation("准备插入Customer,当前Id值:{Id}", dm.Id); context.Add(dm); context.SaveChanges(); return Mapper.Map<Models.Customer>(dm); } catch (DbUpdateException ex) when (ex.InnerException is SqlException sqlEx && sqlEx.Number == 544) { // 544是IDENTITY_INSERT错误的SQL错误码 _logger.LogError(ex, "触发IDENTITY_INSERT错误,尝试重新执行"); // 使用新的DbContext实例重试 using (var newContext = new YourDbContext(_contextOptions)) { var dm = Mapper.Map<Infrastructure.Customer>(customer); newContext.Add(dm); newContext.SaveChanges(); return Mapper.Map<Models.Customer>(dm); } } }
内容的提问来源于stack exchange,提问作者Giorgi Metskhvarishvili

