背景:
项目中使用的是EFCore2.1的DbFirst模式,但由于多个项目使用了相同的基础框架,每次同步更新数据库结构很麻烦,因此同时使用了CodeFirst来进行迁移实现同步。其中,项目A的数据库版本为最新,项目B为旧,现要自动将B项目的数据库结构和A项目保持一致。
过程介绍:
首先要知道,CodeFirst中的Update-database可以实现数据库的创建和结构更新,但结构更新必须有前一次的迁移记录,否则无法自动比对变化,也就无法进行准确的升级更新。
项目B正是这样,从未进行过迁移,因此,需要先生成初始化迁移记录,为下一步的更新做准备:
(1)在程序控制台中执行指令 Add-migration ProjectB_DatabaseInit -c DefaultContext。 其中,-c DefaultContext是因为我的项目中有多个Context,所以要声明
(2)可以看到项目中出现了MIgrations文件夹,以及对应的迁移记录文件。
(3)执行后Update-database ProjectB_DatabaseInit -c DefaultContext,会提示“数据库中对象XXX已存在”的错误,这是因为数据库已存在了,而由于刚才是第一次执行Migration,所以示为创建数据库及表,这就导致了冲突。
(4)打开Migrations文件夹中的迁移记录文件,其中有Up和Down两个方法,其中Up方法中的内容主要是进行创建表的, 把里面在数据库中已存在表的CreateTable语句删除掉(或者直接把Up方法下的代码全删掉,Up方法保留)
(5)重新执行Update-database ProjectB_DatabaseInit -c DefaultContext,成功后在数据库中有一个新的表:_EFMigrationsHistory,可以查看到迁移记录。
注意:这个日志记录和Migrations文件夹中的迁移记录文件是对应的,如果没用特殊情况,请不要删除任何一个,否则会导致后续迁移失败。
(6)通过以上步骤,我们就完成了已有表数据库的初始化迁移记录的创建,为后续同步做好了准备。
(7)由于迁移的基础是DBContext和Model,所以把项目B中的Context和Model文件都和项目A保持一致(Context和Model是使用EFCore-DBFirst Scafolding生成的,复制粘贴都会吧),然后在程序控制台中执行指令 Add-migration ProjectB_DatabaseUpdate -c DefaultContext
(8)再执行Update-database ProjectB_DatabaseUpdate -c DefaultContext
(9)执行完成后查看数据库表,发现已经同步了。
总结:
(1)以上场景虽然比较特殊,但可以帮助我们更好的理解CodeFirst的迁移原理。
(2)Add-Migration生成的迁移文件用于指导Update-database的执行,所以可以通过修改迁移文件来更灵活的进行迁移
(3)DbFirst和CodeFirst各有好处,可同时使用,发挥特点
(4)CodeFirst可以帮我们快速创建数据库,特别是对于不同版本、类型的数据库环境中快速创建表结构。也可以借助CodeFirst生成Sql语句来创建: Script-Migration -Output D:\InitialCreate.sql
(5)如果要反转迁移(即撤销本次迁移),使用 Remove-Migration -c DefaultContext ,如果有多个迁移版本,则执行多次此指令,会按远近依次删除迁移文件。如果迁移已经Update到了数据库,则要在数据库中找到_EFMigration表并删除其中的记录,之后再Remove-Migration
尾声:无图才是纯干货