背景:
項目中使用的是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
尾聲:無圖才是純干貨