Entity Framework Core对接已有数据库执行InitialCreate迁移失败问题问询
EF Core对接现有数据库首次迁移报错解决方案
问题根因
你遇到的报错是因为EF Core迁移依赖__EFMigrationsHistory系统表跟踪已执行的迁移,你从现有数据库脚手架生成模型后,首次创建的InitialCreate迁移包含全量表创建逻辑,但现有数据库没有__EFMigrationsHistory表,执行Update-Database时EF Core会默认从第一个迁移开始执行,就会尝试创建已经存在的表。
以下两种方案均可实现「新环境正常执行建库建表,已有数据库环境跳过初始逻辑不报错」的需求:
方案一:基线迁移(官方推荐,无数据库绑定)
该方案不需要修改自动生成的迁移代码,兼容性更强。
- 确保生成的
InitialCreate迁移的Up、Down方法代码完整,不要注释任何内容,这部分代码用于新环境的全量初始化。 - 针对已经存在TestDB的环境,只需要将
InitialCreate迁移标记为已执行,不需要执行建表逻辑,执行如下命令:
该命令会自动在现有数据库中创建Update-Database InitialCreate --skip-applying-migration__EFMigrationsHistory表,并插入InitialCreate迁移的执行记录,不会运行任何建表逻辑,不会触发已有对象报错。 - 后续新增迁移后,所有环境统一执行
Update-Database即可:新环境会从InitialCreate开始执行全量迁移,现有环境会从InitialCreate之后的新增迁移开始执行。
如果你使用的EF Core版本低于5.0,没有
--skip-applying-migration参数,可以手动执行SQL完成标记:-- 先创建迁移历史表 CREATE TABLE [__EFMigrationsHistory] ( [MigrationId] nvarchar(150) NOT NULL, [ProductVersion] nvarchar(32) NOT NULL, CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) ); -- 插入InitialCreate迁移记录,MigrationId替换为你生成的迁移文件名前缀(如20240520123456_InitialCreate),ProductVersion替换为你使用的EF Core版本号 INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) VALUES (N'20240520123456_InitialCreate', N'7.0.18');
方案二:迁移逻辑加存在性判断(适合无需跨数据库类型的场景)
如果不想针对现有环境执行额外命令,可以直接修改InitialCreate迁移的Up方法,增加SqlServer的表存在判断:
protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql(@" IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Parent' AND schema_id = SCHEMA_ID('dbo')) BEGIN -- 此处保留EF Core自动生成的所有建表、加约束的代码 CREATE TABLE [Parent] ( [Id] int NOT NULL IDENTITY, [Name] nvarchar(400) NOT NULL, CONSTRAINT [PK_Parent] PRIMARY KEY ([Id]) ); CREATE TABLE [Child] ( [Id] int NOT NULL IDENTITY, [Name] nvarchar(400) NOT NULL, [ParentId] int NOT NULL, CONSTRAINT [PK_Child] PRIMARY KEY ([Id]), CONSTRAINT [FK_Child_Parent_ParentId] FOREIGN KEY ([ParentId]) REFERENCES [Parent] ([Id]) ON DELETE CASCADE ); END "); }
修改后不管是新环境还是现有环境执行Update-Database,都会自动判断表是否存在,不存在才执行建表逻辑,不会触发报错。
内容的提问来源于stack exchange,提问作者3xGuy
相关产品推荐
相关产品推荐

