部署ASP.NET Core API到Heroku时报relation Users already exists错误如何解决
问题描述
我正在尝试将使用ASP .NET Core开发的API部署到Heroku平台,部署过程中返回报错:relation Users already exists,麻烦帮忙指出问题所在,提前致谢。
以下是我的迁移代码和收到的报错信息:
protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "Users", columns: table => new { Id = table.Column<Guid>(type: "uuid", nullable: false), Username = table.Column<string>(type: "text", nullable: true), Password = table.Column<string>(type: "text", nullable: true), FirstName = table.Column<string>(type: "text", nullable: true), LastName = table.Column<string>(type: "text", nullable: true), BirthDay = table.Column<DateTime>(type: "timestamp without time zone", nullable: false), Phone = table.Column<string>(type: "text", nullable: true), Role = table.Column<int>(type: "integer", nullable: false) }, constraints: table => { table.PrimaryKey("PK_User", x => x.Id); }); migrationBuilder.InsertData( table: "Users", columns: new[] { "Id", "BirthDay", "FirstName", "LastName", "Password", "Phone", "Role", "Username" }, values: new object[] { new Guid("00000000-0000-0000-0000-000000000001"), new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), "Admin", "01", "d34b21af1ebb547742f2a78124c73764", null, 2, "admin" }); }
报错内容如下:
CREATE TABLE "Users" ( "Id" uuid NOT NULL, "Username" text NULL, "Password" text NULL, "FirstName" text NULL, "LastName" text NULL, "BirthDay" timestamp without time zone NOT NULL, "Phone" text NULL, "Role" integer NOT NULL, CONSTRAINT "PK_User" PRIMARY KEY ("Id") ); Unhandled exception. Npgsql.PostgresException (0x80004005): 42P07: relation "Users" already exists
解决方案
这个报错对应PostgreSQL标准错误码42P07,含义是你要创建的Users表在目标Heroku Postgres数据库中已经存在,导致EF Core执行迁移时触发冲突,你可以按以下场景排查解决:
- 场景1:迁移被重复执行
Heroku的Postgres数据库是持久化存储的,不会随应用重启或重新部署清空数据。如果你配置了应用启动时自动执行所有迁移,且之前的部署已经运行过一次这个建表迁移,就会触发重复建表报错。- 如果你是测试环境且表里没有需要保留的数据,可以手动连接到Heroku Postgres数据库,删除已有的
Users表后重新部署即可。 - 如果需要保留表内现有数据,直接删除当前迁移里的
CreateTable相关代码,只保留增量修改的逻辑即可。
- 如果你是测试环境且表里没有需要保留的数据,可以手动连接到Heroku Postgres数据库,删除已有的
- 场景2:表名大小写冲突
PostgreSQL默认对未加双引号的标识符大小写不敏感,你的迁移代码里建表时用了带双引号的"Users",如果之前手动操作或者其他逻辑建过全小写的users表,也会触发这个冲突。
你可以在DbContext的OnModelCreating方法中加入以下配置,统一将所有表名转为小写,规避大小写敏感问题:
protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { entityType.SetTableName(entityType.GetTableName().ToLower()); } }
- 场景3:EF迁移历史表记录缺失
EF Core会通过__EFMigrationsHistory表记录已经执行过的迁移,如果该表中缺少本次建表迁移的记录,EF会认为这个迁移从未执行过,就会重复触发建表逻辑。
如果确认现有Users表的结构和迁移中定义的完全一致,你可以手动在__EFMigrationsHistory表中插入一条当前迁移的记录,跳过这次建表步骤。
内容的提问来源于stack exchange,提问作者Hieu Le
相关产品推荐
相关产品推荐

