You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 6.0中SET IDENTITY_INSERT ON配置不生效问题排查

问题根因

报错来自两个核心配置/逻辑错误:

  • IDENTITY_INSERT是会话级生效的SQL Server配置,EF Core默认会将独立调用的ExecuteSqlRaw放在单独的连接会话中执行。你之前分开写的开IDENTITY_INSERT、SaveChanges、关IDENTITY_INSERT三个操作根本不在同一个数据库会话里,等SaveChanges执行时,之前开启的IDENTITY_INSERT已经随连接释放自动关闭,自然会触发IDENTITY_INSERT为OFF的报错。
  • 实体属性配置逻辑错误:ValueGeneratedNever()会告知EF Core该列永远不由数据库生成值,会直接导致日常新增业务数据时自增逻辑失效;只配置ValueGeneratedOnAdd()不做额外标记的话,EF Core会默认忽略你传入的TicketId值,强制使用数据库自增生成值,两种配置都不符合你「默认自增、导入时允许手动指定ID」的需求。
正确实现方案

第一步:修正实体列配置

首先调整TicketId的映射配置,明确标记为自增IDENTITY列,适配默认自增的需求:

public void Configure([NotNull] EntityTypeBuilder<Ticket> builder)
{
    builder.HasKey(_ => _.TicketId);
    builder.Property(e => e.TicketId)
        .ValueGeneratedOnAdd()
        .UseIdentityColumn(); // 明确指定使用SQL Server原生IDENTITY自增逻辑,不要配置ValueGeneratedNever()
    // 其余实体配置保持不变
}

如果之前已经生成过数据库迁移,需要补一个迁移确认TicketId列被正确创建为IDENTITY自增列。

第二步:同会话执行导入逻辑

必须将开启IDENTITY_INSERT、插入数据、关闭IDENTITY_INSERT的操作放在同一个事务、同一个数据库连接内执行,避免会话切换导致配置失效,参考实现代码:

// 开启事务,保证整个导入流程共用同一个数据库连接会话
using var transaction = dbContext.Database.BeginTransaction();
try
{
    // 开启指定表的IDENTITY_INSERT,必须写全schema名,你的表在Corporate架构下就写Corporate.Ticket
    dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Corporate.Ticket ON");

    // 逐个标记导入的Ticket实体:ID是显式指定的,不需要EF Core生成临时值、也不需要数据库自增
    foreach (var ticket in importTicketList) // importTicketList是你从供应商API拉取的、带固定TicketId的存量数据集合
    {
        dbContext.Entry(ticket).Property(t => t.TicketId).IsTemporary = false;
        dbContext.Set<Ticket>().Add(ticket);
    }

    // 执行插入
    dbContext.SaveChanges();

    // 插入完成后关闭IDENTITY_INSERT
    dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Corporate.Ticket OFF");

    transaction.Commit();
}
catch
{
    transaction.Rollback();
    throw;
}
关于Sequence的说明

不需要使用Sequence。Sequence适合需要跨多张表共享ID生成序列的场景,你当前单表默认自增、仅导入场景手动指定ID的需求,用原生IDENTITY列配合上述实现完全可以满足,额外引入Sequence只会增加不必要的维护成本。

报错排查清单

如果调整后依然报错,逐一核对以下项:

  • 核对IDENTITY_INSERT后的表名是否带正确的schema前缀,漏写Corporate.会导致SQL Server操作dbo schema下的同名表,配置没有落到实际业务表上
  • 确认开启IDENTITY_INSERT到SaveChanges之间没有触发EF Core的连接回收逻辑,不要在这两步之间执行其他会释放连接的操作
  • 连库执行以下SQL确认表结构配置正确,返回值为1才说明TicketId是合法的IDENTITY列:
SELECT COLUMNPROPERTY(OBJECT_ID('Corporate.Ticket'),'TicketId','IsIdentity')

如果返回0,说明之前的迁移脚本没有正确配置自增属性,修正迁移后重新更新表结构即可。

内容的提问来源于stack exchange,提问作者malathyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:39:27