【发布时间】:2022-12-10 12:26:18
【问题描述】:
我们正在使用 EF Core,但我们也将 ef 核心数据库升级到最新版本。在 Postegres 上有一张表:
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 插入值时,出现异常
重复键值违反唯一约束
我创建了一个新数据库来查看 EF Core 如何定义密钥,它是:
GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1).我向其中添加了主键以避免向我们的旧脚本添加大量主键约束。
我们的更新代码显示在这里(
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 ();需要对旧脚本做些什么才能使身份主键起作用?
或者这甚至是问题所在?我不是 postgres 专家。
我们的数据库升级使用脚本直到达到某个版本,然后我们运行每个migration individually。 EF Core 发现自己不会运行初始创建迁移,但它仍然会在
__EFMigrationsHistory表中添加一个条目,这很棒。更新
在我的搜索中,我找到了这个question。在我们更新和创建新数据库期间,我们插入的数据已经设置了主键,因此使用 postgresql 序列不会更新,并且在您第一次插入时会出现重复键异常。要在创建或升级数据库后解决此问题,您可以使用以下脚本:
@"SELECT setval( (SELECT pg_get_serial_sequence( '""<%SchemaName%>"".""<%TableName%>""', '<%KeyName%>')), (SELECT MAX(""<%KeyName%>"") from ""<%SchemaName%>"".""<%TableName%>""), true );";在带有表和主键名称的循环中使用它,可以将所有序列设置为其正确的值。
【问题讨论】:
-
请注意,为什么是
dbSet.Attach (p);?实体已附加。 -
我们正在使用断开连接的实体,因此我们需要附加
-
dbSet.Find返回跟踪的实体。 -
是的,但我们已断开连接,因此未被跟踪
标签: entity-framework-core npgsql