EF Core 迁移:在存在时删除唯一约束

Posted

技术标签:

【中文标题】EF Core 迁移:在存在时删除唯一约束【英文标题】:EF Core Migrations: Drop Unique Constraint when it exists 【发布时间】:2022-01-23 20:16:41 【问题描述】:

上下文

我在 SQL Server 中有一个表,它在表的四列上有一个唯一索引。

当使用 EF Core 迁移中的 migrationBuilder.AlterColumn 时,它首先尝试编写一个无法在 UNIQUE INDEX 上执行的 DROP INDEX 脚本。为了解决这个问题,我可以使用migrationBuilder.DropUniqueConstraint,只要该约束存在。

问题

一些开发者在本地没有数据库,他们会从头开始运行所有的迁移脚本。这意味着将创建UNIQUE INDEX,但没有数据,因此不会有UNIQUE CONSTRAINT。在这种情况下,会因为约束不存在而引发 SQL 异常。

我尝试使用migrationBuilder.Sql 并执行IF EXISTS 语句,它检查约束是否存在,然后删除它。但是,它似乎没有正确执行,或者根本没有执行。

问题?

我的陈述是否有问题,或者有更简单的方法来解决这个问题?

声明

migrationBuilder.Sql(@"
            IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_NAME='CONSTRAINT_NAME')
            BEGIN
                ALTER COLUMN COLUMN_NAME DROP CONSTRAINT CONSTRAINT_NAME
            END");

【问题讨论】:

那么为什么有时会有唯一约束,有时会有唯一索引呢?这听起来不对。 在迁移 InitialCreate 脚本中,我们添加了唯一索引。只有当我们在表中有数据时,约束才会出现。 约束不会神奇地出现。唯一约束创建索引,反之则不行。 这是有道理的。您是否知道当前如何在我们的数据库中存在唯一约束,而无需手动添加任何内容? 可能有人从其他工具(例如 SSMS)添加约束和索引。您不应该在代码优先的应用程序数据库中这样做,因为在某些时候它可能/将会破坏迁移。 【参考方案1】:

根据 cmets,我们确定了问题所在。

我们最初采用 EF Core 数据库优先方法,其中 SSMS 用于编写 UNIQUE CONSTRAINT 脚本,而后者又创建了 UNIQUE INDEX

后来我们使用带有迁移的脚手架来进行InitialCreate 迁移,首先迁移到代码。在这一步中,它生成了modelBuilder 代码来创建UNIQUE INDEX,但不是约束。这意味着我们的迁移脚本不再与我们现有数据库的状态同步,这些数据库最初是数据库优先的。

解决方案是停止尝试在迁移脚本中删除约束(我们甚至不需要),并将其从我们现有的数据库中删除。

【讨论】:

以上是关于EF Core 迁移:在存在时删除唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

在 EF Core 中生成复合唯一约束/索引

EF Core 中是不是有用于唯一约束的数据注释(代码优先)?

EF Core / Sqlite 一对多关系在唯一索引约束上失败

如何使用 Laravel 迁移从列中删除唯一约束?

如何在EF CodeFirst中使用唯一约束

Django:删除唯一约束并创建迁移