EF Core 2.0 Code First自引用表插入报错:无法显式插入标识列
解决EF Core 2.0 Code First插入数据时的IDENTITY_INSERT异常问题
嘿,这个问题我之前也碰到过,其实就是SQL Server的标识列规则和EF Core的默认配置在搞事情,我给你拆解一下解决方案:
问题原因
你的Department实体里的ID列被EF Core默认识别为标识列(自增列),而SQL Server默认不允许手动向标识列插入显式值,只有当IDENTITY_INSERT设置为ON时才能这么做,这就是你调用SaveChanges()时抛出异常的原因。
两种场景的解决方案
场景1:不需要手动指定ID,让数据库自动生成自增ID
这是最常见的业务场景,只需要确保EF Core正确将ID列配置为标识列即可。虽然int类型的主键默认会被识别为标识列,但有时候可能因为配置问题失效,你可以用Fluent API显式配置:
在你的DbContext类中重写OnModelCreating方法:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Department>() .Property(department => department.ID) .UseIdentityColumn(); // 显式指定该列为自增标识列 }
之后插入数据时,不要手动给ID属性赋值,EF Core会自动让SQL Server生成自增ID,自然就不会触发这个异常了。
场景2:需要手动指定ID值(比如数据迁移、导入历史数据)
如果必须手动插入ID值,那就需要临时开启IDENTITY_INSERT,操作完成后再关闭。注意必须在同一个数据库连接中完成这一系列操作,代码示例如下:
using (var context = new YourDbContext()) { // 开启Departments表的IDENTITY_INSERT context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT Departments ON"); // 添加手动指定ID的实体 var newDept = new Department { ID = 50, Name = "研发中心", ParentDepartmentID = 1 }; context.Departments.Add(newDept); // 保存更改 context.SaveChanges(); // 关闭IDENTITY_INSERT,避免影响后续操作 context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT Departments OFF"); }
这里有几个关键点要注意:
- 开启和关闭
IDENTITY_INSERT必须在同一个DbContext实例的生命周期内(也就是同一个数据库连接) - 每次只能对一张表开启
IDENTITY_INSERT - 操作完成后一定要关闭,否则后续对该表的常规插入可能会出问题
额外检查点
你可以先确认下自己是不是在不必要的情况下手动给ID赋了值,比如普通新增数据时,误设置了ID属性,这种情况下只要去掉手动赋值的代码,就能解决问题啦。
内容的提问来源于stack exchange,提问作者Matt Baech
相关产品推荐
相关产品推荐

