实体框架代码迁移 - 初始迁移卡住了

23

我已通过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>());

我是否漏掉了一些明显的东西? 我尝试了这里的解决方案,但它没有起作用: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”-它存在!

非常令人沮丧!


你的迁移目录中是否存在名为201303262144218_Initial.cs的现有文件? - MattSull
是的。我有点困惑——初始迁移是应该为空的,还是应该创建初始状态的数据库?另外,我的数据库和主数据库都没有__MigrationHistory表。 - SturmUndDrang
Initial只是给这个特定迁移命名的名称。有时人们称他们的第一个迁移为initial。如果您有现有的数据库,并且运行add-migration/update-database命令而没有对模型类进行任何更改,则迁移文件将为空。删除文件201303262144218_Initial.cs,然后再次运行两个命令('add-migration newestMigration',然后'update-database')。 - MattSull
7个回答

28

我曾经遇到过同样的问题,即对于一个已经存在的数据库和代码优先模型启用EF迁移。以下步骤可以解决这个问题:

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

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

10
我运行Update-Database命令时遇到了相同的错误。我尝试了"Update-Database -TargetMigration 201304080859556_MyMigration -Force",但出现了"The specified target migration '201304080859556_MyMigration' does not exist. Ensure that target migration refers to an existing migration id"这个错误 - 实际上它是存在的!
还有一个问题可能会导致您最后的错误(也许是之前错误的根本原因)。我曾经遇到过类似的问题,结果发现一些迁移类在不同的命名空间中,而与我的MigrationConfiguration类的命名空间不同。纠正命名空间(包括xxx.Designer.cs文件中的命名空间)可以解决此问题(迁移再次可见并正常工作)。

2
今天我遇到了几乎完全相同的问题(设计文件中的部分类名已更改,很可能是由于代码合并)。一旦我修复了设计文件,我就能够应用所有的迁移。 - DVK
尝试使用“Update-Database -TargetMigration MyMigration -Force”命令。 - gorums
我遇到了这个问题,因为我把我的迁移文件和其他模型放到解决方案内的另一个项目中。我打开了Windows资源管理器并定位到迁移文件夹,然后打开每个文件并将migration###.designer.cs顶部的命名空间更新为新的命名空间。总之,谢谢。 - ebrahim.mr

3

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

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

-FORCE 指定在数据库自动迁移过程中允许数据丢失。

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

进一步阅读:EF Code First Migrations


好的,所以我已经删除了最初的迁移,并运行了Enable-Migrations(带有-Force),但它并没有创建初始迁移。然后我运行了Add-Migration(指定连接字符串),这将创建一个迁移,它将创建整个数据库(而不仅仅是我添加的额外属性)。 - SturmUndDrang
1
然后我使用-FORCE运行Update-Database,结果出现“无法更新数据库以匹配当前模型,因为存在待处理更改且自动迁移已禁用。要么将待处理的模型更改写入基于代码的迁移,要么启用自动迁移”。为什么这么难让它工作? - SturmUndDrang
我也尝试了-examples标志。它只是说“名称Update-Database概述将任何待处理的迁移应用到数据库”,而没有给出任何示例。 - SturmUndDrang

2
你不需要手动删除迁移,可以方便地使用 "最初的回答" 进行删除。
Remove-Migration

如果您需要重新创建迁移脚本,可以使用Add-Migration命令。

在您的情况下,更新数据库失败是因为存在现有表格,请使用以下命令删除它们:

Drop-Database

然后你可以运行Update-Database命令。

这些命令的详细使用说明在这里


注:Original Answer翻译成“最初的回答”未能理解其含义,因此未进行翻译。

1

尝试将旧的数据库版本迁移到新模型时,要么数据库与新模型不匹配,要么出现错误,例如:

成员“Npgsql.PostgresException,Npgsql,Version = 3.2.2.0,Culture = neutral,PublicKeyToken = 5d8b90d52f46fda7”的类型未解析

以下是如何使用自动迁移使其工作:

  1. Delete Migrations folder
  2. Execute enable-migrations
  3. Set this two properties to true in the newly created Configuration.cs

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
    
  4. Execute Update-Database -Force

您的数据库将会被更新至最新版本,并且准备就绪。

希望这能对您有所帮助。


0

1) 在您的项目中删除现有的迁移文件夹,并在Migration_History表中删除任何现有的迁移。

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

add-migration reset

3) 然后从程序包管理器控制台运行以下命令:

Remove-Migration

4) 然后从程序包管理器控制台运行以下命令(InitialMigration是第一个迁移的名称,您可以根据需要命名):

add-migration InitialMigration


0

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

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

这应该可以解决问题。


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