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

如何解决PostgreSQL自增标识列在EF Core中的重复键异常

PostgreSQL + EF Core 自增主键重复键异常问题及解决

问题背景

我们使用EF Core进行数据库操作,同时需要将EF Core之前版本的数据库升级至最新版本。PostgreSQL中存在如下表结构:

CREATE TABLE "DatabaseVersion"  
( 
    "DatabaseVersionId" integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ) PRIMARY KEY, 
    "Version"     varchar(20) NOT NULL,  
    "VersionDate" timestamptz NULL DEFAULT Now(), 
    "Description" varchar(2000) NULL, 
    "AppliedDate" timestamptz NULL DEFAULT Now()
);

在PgAdmin中创建数据库及该表后,执行插入测试语句:

INSERT INTO "DatabaseVersion" ("Version") 
VALUES ('1.0.0.0');

可成功插入第一行,修改版本号后可继续插入,每行的DatabaseVersionId均保持唯一。

异常现象

通过EF Core执行升级并插入数据时,抛出异常:

duplicate key value violates unique constraint

排查细节

创建新数据库查看EF Core生成的键配置,其定义为:

GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1)

已为该字段添加主键约束,避免在旧升级脚本中重复添加大量主键约束。

EF Core侧的更新代码如下(T对应DatabaseVersion实体):

var dbSet = context.Set<T>();

var id = GetKey(context, item);

if (id == 0)
{
    dbSet.Add(item);
}
else
{
    var p = dbSet.Find(id);
    dbSet.Attach(p);

    var a = context.Entry(p);

    if (a != null)
        a.CurrentValues.SetValues(item);
}

context.SaveChanges();

我们的数据库升级流程为:先通过脚本升级到特定版本,再逐个执行EF Core程序化迁移。EF Core会自动跳过初始创建迁移,并在__EFMigrationsHistory表中添加记录,这部分逻辑正常。

解决方案

经排查发现问题根源:在数据库创建或升级过程中,若通过脚本插入了显式指定主键值的数据,PostgreSQL不会自动更新自增序列的当前值。当EF Core后续尝试插入新数据时,自增序列仍从初始值(1)开始生成,从而触发重复键冲突。

解决方法是在数据库创建或升级完成后,执行以下SQL脚本重置所有自增序列的当前值,使其与表中现有主键的最大值同步:

SELECT setval( 
    (SELECT pg_get_serial_sequence( '"<SchemaName>"."<TableName>"', '<KeyName>')),
    (SELECT MAX("<KeyName>") from "<SchemaName>"."<TableName>"),
    true
);

需遍历所有包含自增主键的表,替换脚本中的<SchemaName>(模式名)、<TableName>(表名)、<KeyName>(主键字段名)后执行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:31:06