開啟Migration
1. 通過 Tools->Nuget Package Manager->Package Manager Console 開啟Package Manager Console視窗
2. Default Project選擇當前的DbContext所在的專案
3. 通過命令開啟Migration
Enable-Migrations
開啟之後,DbContext對應的專案中會生成一個Migrations的資料夾, 主要用來存放各個版本自動生成的更新描述檔案
類似於下圖:
初始化庫
通常你新建了模型,在資料庫建庫之後需要執行一次add-migration命令生成一個庫初始化的migration記錄
add-migration 20160201003
後面部分的名字我通常都會按照當天日期拼接當天的版本號組成,另外一種不錯的實踐是按照增加的業務名稱命名,英文名稱會相對好點.
更新庫
庫的更新可以分為手動更新跟自動更新, 通常Code First Migration的文章都會講這裡要通過Update-Database命令來把剛才的變更更新到庫裡面, 通常DEV環境可以這麼做,因為是直連的, 但是我們的Staging與Production環境是不可以直連的,我們要怎麼做呢?
前面有提到可以自動更新,其意思就是說,你通過 add-migration生成了migration指令碼,那當程式啟動的時候,如果發現數庫介面不一致,那這個就需要更新,這個時候如果是自動更新的狀態,那程式會自動執行(從意思上等同於update-database, 產生的效果相同,但是並未實際考證是否也是跑的update-database命令), 因此無論是dev環境還是staging, production都可以通過自動update-database來完成資料庫的更新。
如何設定自動更新
這裡有兩步:
1. 在migrations資料夾下有個configuration的檔案, 程式碼如下:
public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = false; }
AutomaticMigrationsEnable = true 之後, 設定EF為自動做資料庫更新。
2. 在Global.cs或者任何程式啟動的地方加入:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<CustomerDbContext, Configuration>());
這句是設定當前DbContext的一個初始化配置.
潛在的問題
自動遷移,在某些該名稱,或者刪除欄位的時候,會造成現有資料的丟失,這個需要注意,目前我也是在探索過程中,有進一步的研究成果,會在更新博文說明。
【補充部分】
初始化指令碼的更新
public partial class InitDefaultData : DbMigration { public override void Up() { Sql(@" --初始化FileType原始資料 insert into FileType (SysId,FileTypeId,FileTypeName,Status,CreationTime) select NEWID(),10001,'客戶資料',0,GETDATE(); insert into FileType (SysId,FileTypeId,FileTypeName,Status,CreationTime) select NEWID(),10002,'訂單資料',0,GETDATE(); insert into FileType (SysId,FileTypeId,FileTypeName,Status,CreationTime) select NEWID(),10003,'車輛資料',0,GETDATE(); --初始化FileCategory原始資料 insert into FileCategory (SysId,FileCategoryId,FileCategoryName,Status,CreationTime) select NEWID(),1,'圖片',0,GETDATE(); insert into FileCategory (SysId,FileCategoryId,FileCategoryName,Status,CreationTime) select NEWID(),2,'影印件',0,GETDATE(); insert into FileCategory (SysId,FileCategoryId,FileCategoryName,Status,CreationTime) select NEWID(),3,'視訊',0,GETDATE(); insert into FileCategory (SysId,FileCategoryId,FileCategoryName,Status,CreationTime) select NEWID(),4,'Excel檔案',0,GETDATE(); insert into FileCategory (SysId,FileCategoryId,FileCategoryName,Status,CreationTime) select NEWID(),5,'Word檔案',0,GETDATE(); "); } public override void Down() { Sql(@"truncate table FileType"); Sql(@"truncate table FileCategory"); } }
可以通過Sql函式來執行一些自定義的SQL指令碼。