EF Core报错:IDENTITY_INSERT关闭时无法插入SiteCategory标识列值
解决多对多关联时的SqlIdentity插入错误
问题背景
拥有Tags、TagCategories和SiteCategory三张表,其中TagCategories作为中间表实现Tags与SiteCategory的多对多关系。在.NET Core 8项目中通过数据库脚手架生成对应模型及配置代码,创建新Tag并关联指定SiteCategory时触发错误:
SqlException: Cannot insert explicit value for identity column in table 'SiteCategory' when IDENTITY_INSERT is set to OFF。
模型构建代码
Tag模型构建代码
modelBuilder.Entity<Tag>(entity => { entity.HasKey(e => e.Indx); entity.Property(e => e.Tag1) .HasMaxLength(50) .HasColumnName("Tag"); entity.HasMany(d => d.Categories).WithMany(p => p.Tags) .UsingEntity<Dictionary<string, object>>( "TagCategory", r => r.HasOne<SiteCategory>().WithMany() .HasForeignKey("CategoryId") .OnDelete(DeleteBehavior.ClientSetNull) .HasConstraintName("FK_TagCategories_SiteCategory"), l => l.HasOne<Tag>().WithMany() .HasForeignKey("TagId") .OnDelete(DeleteBehavior.ClientSetNull) .HasConstraintName("FK_TagCategories_Tags"), j => { j.HasKey("TagId", "CategoryId"); j.ToTable("TagCategories"); j.IndexerProperty<int>("TagId").HasColumnName("TagID"); j.IndexerProperty<int>("CategoryId").HasColumnName("CategoryID"); }); });
SiteCategory模型构建代码
modelBuilder.Entity<SiteCategory>(entity => { entity.HasKey(e => e.Indx); entity.ToTable("SiteCategory"); entity.Property(e => e.Category).HasMaxLength(18); entity.Property(e => e.ShowInSystem) .IsRequired() .HasDefaultValueSql("((1))"); });
原操作函数
public bool addTagAndTagCategory(Tag tag, int? categoryID) { try { var siteCat = db.SiteCategories.Where(cat => cat.Indx == categoryID).FirstOrDefault(); siteCat.Tags.Add(tag); db.Add(tag); //var TagCategory = new Dictionary<string, object> // { // { "TagId", tag.Indx }, // { "CategoryId", siteCat.Indx } // }; //db.Attach(TagCategory); db.SaveChanges(); var res = tag.Indx != 0 ? true : false; return res; } catch { throw; } }
解决方案
1. 确保SiteCategory主键配置为自增列
在SiteCategory的Fluent API配置中,添加主键自增的配置,明确告知EF该列由数据库自动生成:
modelBuilder.Entity<SiteCategory>(entity => { entity.HasKey(e => e.Indx); // 添加自增列配置 entity.Property(e => e.Indx).UseIdentityColumn(); entity.ToTable("SiteCategory"); entity.Property(e => e.Category).HasMaxLength(18); entity.Property(e => e.ShowInSystem) .IsRequired() .HasDefaultValueSql("((1))"); });
2. 修改操作函数的关联逻辑
调整关联顺序,从新创建的Tag的Categories集合中添加已存在的SiteCategory,避免EF误将已存在的SiteCategory视为新实体插入:
public bool addTagAndTagCategory(Tag tag, int? categoryID) { try { // 用Find替代Where+FirstOrDefault,更高效且确保实体被上下文跟踪 var siteCat = db.SiteCategories.Find(categoryID); if (siteCat == null) return false; // 从Tag的关联集合添加已存在的分类 tag.Categories.Add(siteCat); // 仅添加Tag到上下文,EF会自动处理中间表的插入 db.Tags.Add(tag); db.SaveChanges(); return tag.Indx != 0; } catch { throw; } }
问题原因说明
- 原配置未明确标记SiteCategory的Indx为自增列,EF可能尝试手动插入该列值,而数据库中该列是自增列,导致权限错误。
- 原操作逻辑反向关联(从SiteCategory集合添加Tag),可能导致EF错误地将已存在的SiteCategory标记为待插入状态,调整关联顺序后可避免此问题。
内容的提问来源于stack exchange,提问作者muhammad tally
相关产品推荐
相关产品推荐

