EF Core 7插入SQL Server标识列报错:IDENTITY_INSERT为OFF时无法显式插入值
解决EF Core插入标识列时的SqlException异常
问题场景
使用Entity Framework Core 7和ASP.NET Core Razor Pages开发时,向SQL Server的ZebraSubPrinters表插入数据触发以下异常:
SqlException
Cannot insert explicit value for identity column in table 'ZebraSubPrinters' when IDENTITY_INSERT is set to OFF.
相关代码与信息
- 实体类定义:
public class ZebraSubPrinters { public decimal ID { get; set; } public string BranchCode { get; set; } public string DisplayName { get; set; } public string Category { get; set; } public string PrinterName { get; set; } public string PrinterIP { get; set; } public bool IsActive { get; set; } = true; }
- 通用仓储插入与保存代码:
public virtual TEntity Insert(TEntity entity) { var result = dbSet.AddAsync(entity).Result.Entity; return result; } public void Save() { try { _basecontext.SaveChanges(); } catch (Exception ex) { throw; } }
- 插入执行代码:
public void InsertZebraSubPrinters(ZebraSubPrinters printer) { ZebraSubPrinters ZEB = new ZebraSubPrinters(); ZEB.IsActive = printer.IsActive; ZEB.PrinterName = printer.PrinterName; ZEB.PrinterIP = printer.PrinterIP; ZEB.Category = printer.Category; ZEB.DisplayName = printer.DisplayName; ZEB.BranchCode = printer.BranchCode; aDCSupportUnitOfWork.ZebraSubPrinters.Insert(ZEB); aDCSupportUnitOfWork.ZebraSubPrinters.Save(); }
- SQL Server Profiler捕获的报错语句:
exec sp_executesql N'SET IMPLICIT_TRANSACTIONS OFF; SET NOCOUNT ON; INSERT INTO [ZebraSubPrinters] ([ID], [BranchCode], [Category], [CreatedBy], [CreatedDate], [DisplayName], [IsActive], [PrinterIP], [PrinterName], [SavedDate], [UpdatedBy], [UpdatedDate]) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11); ',N'@p0 decimal(18,2),@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 nvarchar(4000),@p4 datetime2(7),@p5 nvarchar(4000),@p6 bit,@p7 nvarchar(4000),@p8 nvarchar(4000),@p9 datetime2(7),@p10 nvarchar(4000),@p11 datetime2(7)',@p0=0,@p1=N'10207',@p2=N'Green',@p3=NULL,@p4='0001-01-01 00:00:00',@p5=N'TANTAWY',@p6=1,@p7=NULL,@p8=NULL,@p9='0001-01-01 00:00:00',@p10=NULL,@p11='0001-01-01 00:00:00'
补充说明:ID列是主键且为标识列(增量1,1),数据库中数据类型为numeric(18,0),存储值为整数,实体类定义为decimal类型。
问题原因
EF Core未识别到ID属性是数据库的标识列,因此生成插入SQL时自动包含了ID字段(值为decimal类型的默认值0),而SQL Server默认禁止手动插入标识列的值,导致抛出异常。
解决方法
方法1:使用数据注解配置标识列
在实体类的ID属性上添加注解,明确告知EF Core该字段由数据库自动生成:
public class ZebraSubPrinters { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public decimal ID { get; set; } // 其他属性保持不变 public string BranchCode { get; set; } public string DisplayName { get; set; } public string Category { get; set; } public string PrinterName { get; set; } public string PrinterIP { get; set; } public bool IsActive { get; set; } = true; }
方法2:使用Fluent API配置标识列
在DbContext类的OnModelCreating方法中,通过Fluent API配置ID属性为标识列:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ZebraSubPrinters>() .Property(p => p.ID) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // 其他实体配置... }
若要更贴合SQL Server标识列特性,也可使用:
modelBuilder.Entity<ZebraSubPrinters>() .Property(p => p.ID) .UseIdentityColumn();
额外注意事项
- 类型精度匹配:数据库中
ID是numeric(18,0),可通过注解或Fluent API指定精度,避免EF生成不必要的小数位:// 数据注解方式 [Column(TypeName = "numeric(18,0)")] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public decimal ID { get; set; } // Fluent API方式 modelBuilder.Entity<ZebraSubPrinters>() .Property(p => p.ID) .HasColumnType("numeric(18,0)") .UseIdentityColumn(); - 禁止手动赋值:创建
ZebraSubPrinters实例时,不要手动给ID赋值(当前代码未手动赋值,仅用默认值0,配置标识列后EF会自动忽略该值,不再生成到插入SQL中)。 - 更新Code First迁移:若使用Code First模式,配置完成后需生成新迁移并更新数据库,确保实体配置与数据库结构一致。
内容的提问来源于stack exchange,提问作者ahmed abdelaziz
相关产品推荐
相关产品推荐

