注:本文面向的是已經對EF的遷移功能有所了解,知道如何在控制台下進行相關命令輸入的讀者
問題
最近公司項目架構使用ABP進行整改,順帶想用EF的自動遷移代替了以前的手工腳本。
為什么要替代?
請看下圖:

大版本就不用說了,每個小版本的發布我們都要准備一堆數據庫升級腳本,這簡直就是惡夢。
而使用ef它會自動幫我們完成數據庫遷移,而我們只需要維護好遷移腳本就行了。
由於我們是線下項目,並且還有很多客戶在使用老版本,所以我們不得不考慮既存表的問題。
而針對已存在的數據庫,我們進行遷移時,總會出現Table_XXX已存在的問題,
這個很容易理解,因為就算是已存在的數據庫
只要沒有__migrationhistory表,它都會認為是一個新庫而執行創建腳本。
第二個問題是公司需要對某些功能模塊進行單獨迭代和發布,說簡單點就是以插件包的方式安裝某些功能。
用過Orchard的朋友肯定知道它的模塊化機制能夠單獨創建和維護屬於自己部分的表,
沒錯,我們現在就是要實現類似的功能。
解決方案
1,對已存在的數據庫的遷移
對待已存在的數據庫的升級該怎么辦?
其實很簡單,選擇當前的最新的一個發布版本作為一個EF遷移初始版本,所有到初始版本的數據庫升級或則全新安裝都使用DDL腳本進行。
選擇好最新的發布版本后,我們使用
Add-Migration Initial
來創建一個初始化遷移腳本。
然后刪除Up和Down方法體中的所有內容,如下:

然后就可以開始當前迭代的開發了,在DbContext修改完畢后,我們可以使用
Add-Migration XXXXXX_X.X.X(能夠描述當前版本的名字)
來創建一個當前開發版本的遷移腳本,如下。

接下來要做的就是在初始化程序時讓程序自動升級,
我所知道的能做這件事辦法有:
1,通過官網發布的migrate.exe來執行遷移命令。
2,通過編程控制遷移。
3,通過nuget控制台執行Update-Database。
作為一個線下項目,第三種辦法顯然沒法使用了,而第一種需要帶上exe還要寫些腳本,麻煩。
第二種辦法有兩個類可以實現:
1,DbMigrator
var dbMigrator = new System.Data.Entity.Migrations.DbMigrator(new Migrations.Configuration()); dbMigrator.Update();
2,MigrateDatabaseToLatestVersion
new MigrateDatabaseToLatestVersion<CoreServiceDbContext, Configuration>().InitializeDatabase(new CoreServiceDbContext());
不同之處是,前者可以選擇更新的版本,后者如其名,在沒有特別需求的情況下,任選其一即可。
上面的代碼放在程序初始化的時候做就可以了,使用了ABP框架的朋友可以放在Data模塊的PreInitialize做這件事。
或者放在global的application_start事件也不錯。
這樣就解決了對已存在的數據庫進行自動升級的問題。
2,模塊化數據遷移。
這個問題其實很好解決,每個模塊配置自己的EF遷移設置時使用不同的ContextKey即可,如下:
(這是主業務功能的遷移設置)

(某模塊的)

整體安裝之后的遷移表如下:

可以看出各個模塊都有不同的ContextKey且遷移記錄都互不影響。
唯一有點遺憾是,由於我們使用Mysql並不支持DDL的事務管理,導致我們不得不在安裝時手動拷貝整個數據庫來以實現備份。
如果在SQLServer的環境下使用遷移的話,EF是會自動開啟事務的,Oracle不太了解,有驗證過的朋友麻煩留言告訴一聲。
