实体框架代码迁移 - 卡在初始迁移上

Posted

技术标签:

【中文标题】实体框架代码迁移 - 卡在初始迁移上【英文标题】:Entity Framework Code Migrations - Stuck on Initial Migration 【发布时间】:2013-03-17 06:34:17 【问题描述】:

我已通过 Nuget 将 EF 5 添加到我的项目中,并使用“Enable-Migrations”命令启用了迁移。然后我调用了“Add-Migration”来生成用于生成架构的基本代码。

然后,我向我的一个域对象(称为“TestProperty”的字符串属性)添加了一个属性,并向我的 EntityTypeConfiguration 文件添加了一个映射(我们目前忽略了约定)。

再次调用“Add-Migration”会产生错误:

Unable to generate an explicit migration because the following explicit migrations are pending: [201303262144218_Initial]. Apply the pending explicit migrations before attempting to generate a new explicit migration.

但调用“Update-Database”会产生 sql 异常,因为表已经存在:

There is already an object named 'Customer' in the database

在我的 DbContext 构造函数中,我尝试了不同的更新策略,例如:

Database.SetInitializer<UnitOfWork>(new DropCreateDatabaseAlways<UnitOfWork>());

我是否遗漏了一些明显的东西? 我在这里尝试了解决方案,但没有成功:Automatic Migrations for ASP.NET

谢谢

编辑:更新 通过第一步的关键是创建初始迁移,然后从 Up 和 Down 方法中删除生成的代码 (http://thedatafarm.com/blog/data-access/using-ef-migrations-with-an-existing-database/)。

然后我可以更新模型和 EF 映射,然后运行 ​​Add-Migration。这会使用正确的 Up 和 Down 代码生成迁移。

然后问题是尝试应用更新。 Update-Database 产生错误“无法更新数据库以匹配当前模型,因为存在待处理的更改并且自动迁移被禁用...自动迁移。将 DbMigrationsConfiguration.AutomaticMigrationsEnabled 设置为 true 以启用自动迁移。 您可以使用 Add-Migration 命令将挂起的模型更改写入基于代码的迁移”。好的,所以我再次尝试 Add-Migration,它会生成另一个迁移,其代码与上次迁移完全相同。

我运行 Update-Database 并再次遇到相同的错误。我尝试“Update-Database -TargetMigration 201304080859556_MyMigration -Force”,但这会产生“指定的目标迁移 '201304080859556_MyMigration' 不存在。确保目标迁移引用现有的迁移 id” - 确实如此!

非常沮丧!

【问题讨论】:

您的 Migrations 目录中是否有一个名为 201303262144218_Initial.cs 的现有文件? 是的。我有点困惑 - 初始迁移应该是空白还是应该在其初始状态下创建数据库?另外,我没有 __MigrationHistory 表(在我的数据库或主数据库中) Initial 只是该特定迁移的名称。有时人们称他们的第一次迁移为首字母。如果您有一个现有的数据库,并运行 add-migration/update-database 命令而不对模型类进行任何更改,则迁移文件将为空。删除文件 201303262144218_Initial.cs,然后再次运行这两个命令('add-migration latestMigration' then 'update-database'。 【参考方案1】:

我在为具有现有数据库的代码优先模型启用 EF 迁移时遇到了同样的问题,并且以下过程有效:

    删除项目中现有的 Migrations 文件夹,并从现有数据库中删除表 __MigrationHistory。 从包管理器控制台运行enable-migrations 命令。 运行add-migration 命令以创建初始迁移。 删除 Up() 方法中的所有代码以进行初始迁移。 运行update-database 命令将初始迁移应用到您的数据库。 这不会对现有对象进行任何更改(因为Up() 方法不包含任何代码),但会将现有数据库标记为已迁移到初始状态。 更改您的代码优先模型。 运行add-migration 命令创建一个新的迁移。 新迁移的 Up() 方法中的代码将仅包含对您的对象模型的更改。 运行update-database 命令将更改应用到您的数据库。

【讨论】:

如果我删除了表,我以后需要它还是重新创建它? 运行“add-migration”命令时,EF 会自动重新创建“__MigrationHistory”表。 我也发现 Visual Studio 在某些情况下会损坏其模型更改跟踪(例如,在重构期间进行大量模型和迁移更改以获得最佳解决方案),修复它的唯一方法是删除 migrationhistory表或手动回滚更改并从 migrationhistory 表中删除卡住的迁移。我发现这个 EF 模型更改跟踪有时真的很烦人。 Laravel 有迁移,但没有模型跟踪,它工作得很好。我想,这就是模型跟踪的代价——当你想要对抗 EF 自动跟踪时会增加复杂性和问题。 非常好的例程 MrUpsideDown。根据我对至少 net core 版本 2.2.104 和新创建项目的经验,以下适用:enable-migrations 可以省略,Up 方法中所有代码的删除可以省略。【参考方案2】:

我运行 Update-Database 并再次遇到相同的错误。我尝试“Update-Database -TargetMigration 201304080859556_MyMigration -Force”,但这会产生“指定的目标迁移 '201304080859556_MyMigration' 不存在。确保目标迁移引用现有的迁移 id” - 确实如此!

还有一个问题可能会导致您的最后一个错误(并且可能是之前错误的根本原因)。我遇到了类似的问题,结果由于某种奇怪的原因,我的一些迁移类位于与 MigrationConfiguration 类的命名空间不同的命名空间中。更正命名空间(也在xxx.Designer.cs 文件中)解决了这个问题(迁移可见并再次工作)。

【讨论】:

我今天遇到了几乎完全相同的问题(设计器文件中的部分类名已更改,很可能是由于代码合并)。修复设计器文件后,我就可以应用所有迁移。 尝试“更新-数据库-TargetMigration MyMigration -Force” 我遇到了这个问题,因为我将我的迁移文件和其他模型内容移到了解决方案中的另一个项目中。我打开 Windows 资源管理器并定位到迁移文件夹,然后打开每个文件并将迁移###.designer.cs 顶部的命名空间更新为新的命名空间。无论如何,谢谢【参考方案3】:

您是否尝试使用 -force 参数来应用更改。

Update-Database [-SourceMigration <String>]
  [-TargetMigration <String>] [-Script] [-Force] [-ProjectName <String>]
  [-StartUpProjectName <String>] [-ConfigurationTypeName <String>]
  [-ConnectionStringName <String>] [<CommonParameters>]

-强制 指定在自动迁移的过程中数据丢失是可以接受的 数据库。

您可以使用get-help Update-Database -examples 查看使用示例。

进一步阅读:EF Code First Migrations

【讨论】:

好的,我已经删除了初始迁移。并运行尚未创建初始迁移的 Enable-Migrations(使用 -Force)。然后我运行 Add-Migration(指定连接字符串),它创建了一个迁移,该迁移创建了整个数据库(不仅仅是我添加的额外属性)。 然后我使用 -FORCE 运行 Update-Database,我得到“无法更新数据库以匹配当前模型,因为有待处理的更改并且自动迁移被禁用。要么将待处理的模型更改写入代码-based 迁移或启用自动迁移”。为什么让这个工作这么难? 我也尝试了 -examples 标志。它只是说“NAME Update-Database SYNOPSIS 将任何挂起的迁移应用到数据库”,而没有给出任何示例。【参考方案4】:

您不需要手动删除迁移,使用方便删除它

Remove-Migration

然后您可以使用Add-Migration 重新创建迁移脚本。

在你的情况下,更新数据库失败,因为有现有的表,删除它们

Drop-Database

那你可以Update-Database

这些命令的更详细用法是here。

【讨论】:

【参考方案5】:

尝试将旧数据库版本迁移到新模型,数据库与新模型不匹配,或者我收到如下错误:

类型未解析成员 'Npgsql.PostgresException,Npgsql, 版本=3.2.2.0,文化=中性,PublicKeyToken=5d8b90d52f46fda7'

它是这样工作的(使用自动迁移):

    删除迁移文件夹 执行启用迁移

    在新创建的 Configuration.cs 中将这两个属性设置为 true

    public Configuration()
    
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    
    

    执行更新数据库-Force

您的数据库将更新为最新方案并准备就绪。

希望这会有所帮助。

【讨论】:

【参考方案6】:

这是一种通常有效的一揽子方法:

    删除整个 Migrations 文件夹(确保复制您可能从迁移配置文件中的种子方法创建的任何代码)。 删除实际数据库。如果您使用的是 LocalDb,它通常位于您的 AppData 解决方案文件夹中(右键单击 -> 打开文件夹位置)。确保删除 .mdf 和 .log 数据库文件。 转到包管理器控制台。输入enable-migrations -projectname yourprojectname 转到包管理器控制台。输入add-migration "Initial" -projectname yourprojectname。 打开迁移配置文件并将您从第 1 步复制的代码粘贴到种子方法中。 转到包管理器控制台。输入update-database -projectname yourprojectname

这应该可以解决问题。

【讨论】:

【参考方案7】:

1) 删除项目中现有的 Migrations 文件夹,并从 Migration_History 表中删除现有迁移(如果有)。

2)从包管理器控制台运行以下命令:

添加迁移重置

3) 之后,从包管理器控制台运行以下命令:

移除-迁移

4) 之后,从包管理器控制台运行以下命令(InitialMigration 是第一次迁移的名称,您可以随意命名):

添加迁移初始迁移

【讨论】:

以上是关于实体框架代码迁移 - 卡在初始迁移上的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码在数据库迁移后首先回滚

在实体框架核心中合并迁移

实体框架迁移:序列包含多个匹配元素

实体框架 - 迁移 - 代码优先 - 每次迁移播种

实体框架代码首先迁移两个不同的数据库

实体框架代码优先迁移 - 我可以针对以前的迁移