无法使用现有数据库运行EF5迁移
首先,我已经阅读了这些问题/答案:
- EF迁移消息
- 如何在使用基于代码的迁移时停止添加迁移检查我的数据库没有挂起的迁移?
- 使EF4.3代码优先迁移忽略挂起的迁移
这些似乎都适用于EF5之前的EF版本,我的情况似乎不适合这些答案。 所以,让我描述一下我的情况。
- 我的应用程序最初是使用EF4创建的,模型优先。 我使用GUI设计器设计了我的数据库,并用它来生成我的数据库。
- 我已经运行并将数据收集到数据库中几个月了。 我真的不能丢失这些数据。
- 我分支我的代码,用NuGet安装EF5,并使用EF Power Tools通过右键单击新的类库项目从我的数据库生成我的模型,然后选择
Entity Framework | Reverse engineer code first
Entity Framework | Reverse engineer code first
。 - 我能够顺利地重新引用我的新项目,将我的项目转换为使用新的DbContext而不是ObjectContext,并删除了保存旧模型的EF4类库。 该计划效果很好!
现在,我想尝试自动迁移,我在Ruby on Rails中有一些经验。 这是我做的:
- Ran
Enable-Migrations
。 由于连接字符串和app.config被使用而有点麻烦,但最终得到了它。 但是, 这个MSDN页面说这应该自动生成第一次迁移,以使我达到我已经到达的程度。 它没有。 - Ran
Add-Migration InitialSchema
来完成在步骤1中未自动完成的操作。这有效。 - 向我的某个模型对象添加了一个属性,然后尝试运行
Add-Migration AddSerialToLogEntries
,并显示:
由于以下显式迁移未决,因此无法生成显式迁移:[201307190100268_InitialSchema]。 在尝试生成新的显式迁移之前应用挂起的显式迁移。
尝试在我现有的数据库上应用迁移失败,这并不奇怪。
我上面提到的其他答案基本上说我运气不好,但就像我说的那些是旧版本的entity framework。 我有什么选择吗?
在写这个问题时,我想我可以使用SQL Server Management Studio将我的数据导出到SQL脚本,删除整个数据库,让EF创建它,然后运行脚本来重新获取我的数据……我会在明天有空的时候尝试,但我想知道是否还有其他选择,因为我不是100%肯定会工作,并且不愿意在流程中插入的数据中出现任何错误。
Ran Enable-Migrations。 由于连接字符串和app.config被使用而有点麻烦,但最终得到了它。 但是,这个MSDN页面说这应该自动生成第一次迁移,以使我达到我已经到达的程度。 它没有。
Ran Add-Migration InitialSchema来完成在步骤1中未自动完成的操作。这有效。
实际上,只有在已使用Code-First创建数据库之前, enable-migrations
命令才会创建初始迁移,在此情况下,数据库包含__MigrationHistory
表。 如果此表不存在(具有以前从未使用Code-First创建的现有数据库的情况),则enable-migrations
仅创建Configuration
类。 您必须手动调用add-migration
,然后创建第一个迁移类。 所以,你所看到的行为是预料之中的。
通常,如果使用EF 5,则为迁移准备现有数据库的过程如下:
-
在包管理器控制台中调用
enable-migrations
。 将创建项目中的Migrations
文件夹和Configuration
类。 -
打开
Configuration
类并在构造函数中设置AutomaticMigrationsEnabled = false
(如果默认情况下尚未设置)。 -
在包管理器控制台调用中
add-migration -IgnoreChanges InitialSchema
“InitialSchema”只是一个示例名称。 您可以按照自己的意愿命名。 将创建一个从
DbMigration
派生的
类。 由于_InitialSchema -IgnoreChanges
标志,此类中的Up
和Down
方法为空。 如果没有此标志,则类将包含迁移以将整个模型添加到数据库,这不是您想要的,因为现有数据库已包含数据库模式。 -
在包管理器控制台中运行
update-database
。 因为Up
方法为空,所以此更新不会对现有模式执行任何操作, 除非它创建__MigrationHistory
表(作为数据库中的系统表),并将第一条记录添加到此表中,其中包含当前EF模型的模型哈希。 -
可选的最后一步:如果您更喜欢使用自动迁移,请打开
Configuration
类并在构造函数中设置AutomaticMigrationsEnabled = true
。 如果要继续进行基于代码的迁移,请将标志设置为false
。
此时,您可以开始对模型进行更改。 每次使用add-migration
创建新迁移时,它都将在修改之前基于您的模型,迁移类将仅包含必要的模式更改。
我建议采用稍微不同的方法,使您处于可以使用迁移在开发环境中从头开始创建数据库的状态:
-
而不是调用
add-migration -IgnoreChanges InitialSchema
,尝试使初始模式迁移的生成工作。 正如您所说,这应该在您最初调用Enable-Migrations
时发生。 您可以尝试将数据库连接指向不存在的数据库,以使其工作。 -
因此,您的
InitialSchema
迁移将包含创建数据库的逻辑,就像您在逆向工程时一样。 您需要注释掉Up()
和Down()
的内容,直到您已部署到已有现有数据库的所有环境。 -
然后,您可以取消注释这些方法的内容,从那时起,在开发环境中,您可以删除数据库并使用它们重新创建它们。
var migrator = new DbMigrator(new Configuration()); migrator.Update();
并且您将在
__MigrationHistory
表中拥有完整的迁移集。 这很重要,因为没有它,您将来无法添加新的迁移。