在Entity Framework Core中合并迁移

28

是否有可能将所有迁移文件合并为一个?

我创建了初始迁移。

dotnet ef migrations add InitialMigration

每当我有一些模型更改时,我就会创建新的迁移更新。

但现在我有太多的迁移更新文件了。 是否可能将所有迁移文件合并为一个?

当然,删除数据库不是选项,我必须保留数据!


1
毫无意义,你的数据库可能处于任何迁移状态。例如,如果你有6个迁移,并且你的数据库在第4个迁移阶段,但是如果你将3到6合并成一个迁移文件,你就永远无法升级你的数据库,因为它停留在第4个迁移阶段。 - Tseng
你可以做的最好的事情是,如果你有15个迁移,回滚到第2个迁移,然后创建一个新的迁移。但是,如果你的应用程序在不同状态的多个服务器上运行(你永远不能回滚到正在使用的最旧的迁移之前),那么仍然存在问题。 - Tseng
为了解决上述评论中的问题,首先将所有数据库迁移到最新版本。然后,删除所有迁移脚本文件,包括模型快照(重要)。接下来,删除__EFMigrationsHistory表中的所有记录,并添加一个新的记录,其名称与您创建的单个迁移文件相同。这是保留所有表中数据的方法。 - Miro J.
5个回答

44

EF 6.X具有一个选项IgnoreChanges,这非常适合您的情况。但不幸的是,它不是EF core中可用的功能。

但是有一种解决方法。

步骤1:删除Migrations文件夹中的所有迁移脚本。

步骤2:在程序包管理器控制台中运行:

PM> Add-Migration InitialCreate

步骤3: 删除Up()Down()方法的代码。在执行此操作之前,请将这些方法另存为,因为我们将在步骤5中需要它们。

步骤4:运行:

 PM> Update-Database

它将向__EFMigrationsHistory表中插入新记录。

步骤5:之后,从在步骤3中保存的内容中填写上述迁移脚本(即.._InitialCreate)的Up()Down()方法。

就这样。现在您只有1个迁移文件:)

注意:EF Core与包管理器控制台(PM):Package Manager Console


2
这不是一个好的解决方案。它必须明确指出这是一个坏主意,并且在将其应用于生产环境之前,应该仅在测试环境中小心使用。 - Adelaiglesia
7
在第三步中,不要删除Up()Down()方法的代码,而是将Up()方法注释掉,然后在最终的第五步中取消注释即可。请注意,注释是通过在代码前面添加双斜杠(//)实现的。 - S.Serpooshan
1
我使用的最佳解决方案是在数据库优先模式下工作(使用edmx和/或数据库项目)。我不明白为什么微软删除了这个选项。这种方法更高效(您可以真正微调数据库以提高性能),在部署到新服务器时问题较少(只需将数据库项目发布到SQL服务器或生成一个脚本即可在2秒钟内完成),EDMX模型可以保持代码模型和数据库同步,... - FredPonch
1
Db first并没有消失。EDMX可视化设计工具存在缺陷,而且并不是必需的。它在EF Core中的精神继承者是Scaffold-DbContext,它可以从现有数据库模式中美妙地反向工程出实体模型。这也使得从现有数据库进行代码优先开发变得容易。如果数据库仅用于服务应用程序,则代码优先是更好的选择,特别是用于部署。如果没有代码优先迁移,那么在推广到分段/生产环境时,必须分别对应用程序和数据库进行更改。 - Patrick Borkowicz
2
该方法似乎会丢失像在 Up()Down() 中使用的 migrationBuilder.Sql() 这样的原始 SQL 语句。 - mu88
显示剩余7条评论

8
当你想要合并最后N个迁移而不是全部时,该协议不同:
1. 撤销最后N个迁移,逐个执行以下2个命令: - dotnet ef database update NameOfTheLastMigration - dotnet ef migrations remove 2. 将撤销应用于数据库: - dotnet ef database update 3. 创建“合并”迁移: - dotnet ef migrations add NameOfTheMergeMigration

2
还原将删除您添加的所有列,包括其中的数据。 - Miro J.

6

一种方法是物理删除所有迁移文件并添加新文件。如果您的迁移位于“迁移”文件夹中,则可以简单地将其删除,否则您还需要删除“ModelSnapshot”文件。我认为这种方法可以解决您的问题。


0
这是我发现最有效和更容易的方法来做到这一点:
  1. 如果尚未应用最新的迁移,请先应用它们。
  2. 从数据库中删除_EFMigrationsHistory表中的所有行。
  3. 从项目中删除迁移文件夹。
  4. 使用包管理器控制台或dotnet ef cli创建一个新的迁移。
  5. 将新创建的迁移的名称(不带扩展名)复制并插入到_EFMigrationsHistory表中,同时附上您的dotnet ef工具版本。

0
作为一名.NET C#开发者,我得出结论,EF迁移在与源代码控制接口设计方面相当不好,因为它们每个迁移都会存储大量的二进制模式数据(对于源代码控制系统来说很糟糕),并且在尝试合并来自多个GIT分支的迁移时会导致无休止的麻烦(对于团队工作流程来说很糟糕)。因此,我最终放弃了EF迁移,并用更简单的东西取而代之,这也适用于GIT合并和我们的DBA(他们只关心SQL)。
我选择了FOSS应用程序MyBatis/Migrate,它可以与任何支持JDBC的SQL引擎一起使用。我已经将其用于SQL Server、MySQL和Oracle(尚未使用Postgres)。我还将其用于C# / EF项目(我只是停止使用EF的迁移)。对于初学者来说,这是一个毫无头脑的选择。没有依赖关系,所以可以用于任何SQL数据库项目和任何应用程序语言。由于它是纯SQL,您可以利用特定于您的SQL方言的功能(例如,在MySQL中,您可以使用MySQL特定的AFTER子句在任何现有列之后添加新列,而不必强制将其添加到表的末尾)。
您只需使用它们的“migrate new”命令创建带有时间戳的SQL脚本,其中包含模式或数据迁移的正向和回滚SQL代码。使用以时间戳为前缀的文件名(而不是版本号)意味着您的软件团队可以轻松地创建并随后合并来自不同git分支的多个迁移文件 - 太容易了!它们将被组合并作为单个发布的一部分应用于数据库。如果您确实需要执行复杂的数据迁移,则可以编写存储过程,或者可以编写Java类作为迁移的一部分(尽管这对您的DBA没有帮助)。
对于不想处理VS或.NET的DBA,您可以使用“migrate script”命令生成正向或回滚SQL脚本,该脚本收集要应用于给定软件发布的迁移序列。
您可以配置多个数据库实例(例如开发,测试,阶段,生产),只需使用“--env”选项选择要将SQL迁移应用于哪个实例(例如“--env = stage”)。在每个数据库实例中,它创建一个“CHANGELOG”表,跟踪已应用的迁移。
要开始...安装Java JDK 8,然后安装此应用程序。 例子:

$ migrate status   #  Shows migrations applied and "pending" (be applied) to the selected database 
$ migrate up 1     # Applies the next migration
$ migrate down 1   # Undo the last migration 

$ migrate redo 1   # Undo and apply last migration (handy when developing migrations)

$ migrate up       #  Applies all pending migrations 

$ migrate --env=test status   # Show status of the `test` database.

# Emit forward and reverse SQL for a sequence of migrations. 
# Just what your DBAs wanted!
$ migrate script 20090804225207 20090804225333 > up.sql    
$ migrate script 20090804225333 20090804225207 > down.sql  

在YouTube上观看《MyBatis模式迁移》。如果您更喜欢使用C#代码,您可能想看看Fluent Migrator。它特别适用于需要支持多个数据库平台的产品项目。我曾经在一个同时支持SQL Server和MS-Access的项目中使用过它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接