項目中用到了EF Code First和遷移,但發現有些方面似懂非懂。比如:如何在遷移文件中控制遷移過程?如果在遷移文件中執行SQL語句?如何使用Update-Database的其它參數?資料庫在生產環境的時候如何遷移?於是就有了下麵的這些體驗:enable-migration第一次生成資料庫時使用
項目中用到了EF Code First和遷移,但發現有些方面似懂非懂。比如:如何在遷移文件中控制遷移過程?如果在遷移文件中執行SQL語句?如何使用Update-Database的其它參數?資料庫在生產環境的時候如何遷移?於是就有了下麵的這些體驗:
enable-migration
第一次生成資料庫時使用。
→ enable-migration
→ 在類庫下多了Migrations文件夾,包含Configuration.cs和每次的遷移記錄文件
每次的遷移文件大致是:
public partial class InitialCreae : DbMigration { public override void Up() { CreateTable( "Aliases", c => new { Id = c.Int(nullable: false, identity: true), Name = c.String(nullable: false), UserName = c.String(maxLength:30), Email = c.String(), Bio = c.String(), CreateDate = c.DateTime(nullable: false) } ) .PrimaryKey(t => t.Id); CreateTable( "Tweets", c => new { Id = c.Int(nullable: false, identity:true), CreateDate = c.DateTime(nullable: false), AliasId = c.Int(nullable:false) } ) .PrimaryKey(t => t.Id) .ForeignKey("Aliases", t => t.AliasId, cascadeDelete: true) .Index(t => t.AliasId); } public override Down() { DropIndex("Tweets", new[]{"AliasId"}); DropForeignKey("Tweets", "AliasId", "Aliases"); DropTable("Tweets"); DropTable("Aliases"); } }
遷移的配置文件大致是:
internal sealed class Configuration : DbMigrationsConfiguration<TweeterContext> { public Configuration() { AutomatecMigrationsEnabled = false; } protected override void Seed(TwitterContext context) { } }
資料庫初始化
Database.SetInitializer(new MigrateDatabaseToLastesVerstion<TwitterContext, Configuration>());
自動或手動遷移設置
public class Configuration : : DbMigrationsConfiguration<TweeterContext> { public Configuration() { //如果手動遷移,設置成false AutomaticMigrationsEnabled = true; //即使列中有數據,這個列也可以被刪除,刪除的時候只是少了該列的數據 AutomaticMigrationDataLossAllowd = true; } }
Add-Migration
每次遷移保存在本地。
配置文件大致如下:
public class Configuration : DbMigrationsConfiguration<TwitterContext> { public Configuraiton() { AutomatcMigrationsEnabled = false; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(TwitterContext context) { } }
→ 比如增加一個列
→ 運行: Add-Migration somename
→ 遷移文件大致是
public partial class AddSomeColumnToSomeTable : DbMigration { public override void up() { AddColumn("sometable", "somecolumn", c => c.String()); } public override void Down() { DropColumn("sometable", "somecolumn"); } }
Update-Database
更新資料庫,執行沒有被執行的遷移文件。
→ 執行:update-database -verbose
verbose表示顯示更新明細,會顯示執行了哪些遷移,執行了哪些SQL語句。
→ 其它參數
TargetMigration
Script & SourceMigration:創建SQL語句
Force:允許數據丟失
ProjectName:DbMigrationsConfiguraiton所在的類庫
ConfigurationTypeName:DbMigrationsConfiguration的繼承類
SartUpProjectName:連接字元串所在的類庫
ConnectionString & ConnectionProviderName:明確連接字元串或provider
或者通過:get-help update-database -detailed, 瞭解更多。
回滾
Update-Database -TargetMigration:"SomeMigrationName" -verbose
在遷移文件中自定義一些遷移動作,控制遷移過程
所有的遷移文件繼承自DbMigration這個類,該類提供了很多方法供我們控制遷移過程。
→ 比如讓增加的類有一個預設值
public partial class AddSomeColumn : DbMigration { public override void Up() { AddColumn("sometable", "somecolumn", c => c.String(defaultValue: "sth")); } public override void Down() { DropColumn("sometable", "somecolumn"); } }
執行SQL語句
比如,現有數據的某些列為NULL,如果想給這些行的該列附上值,該如何做呢?
→ 改變領域模型
→ 執行:Add-Migration somename
→ 在遷移文件中執行SQL語句
public partial class AddSome : DbMigration { public override void Up() { AddColumn("table", "column", c => c.String(maxLength:10)); Sql("Update table set column='sth'"); } public override void Down() { DropColumn("table", "column"); } }
→ Update-Database -verbose
資料庫的種子數據
public class Configuration : DbMigrationsConfiguraiton<TwitterCotext> { public Configuration() { AutomaticMigrationsEnabled = false; AutomaticMigraitoinDataLossAllowed = true; } protected override void Seed(TwitterContext context) { context.Aliases.AddOrUpdate(a => a.Name, new Alias{}, new ALias()) } }
對生產環境下的資料庫作遷移
→ 執行:udb -script -verbose
→ 彈出一個可以編寫sql語句的視窗,此時沒有與資料庫連接
alter table sometable add column nvarchar(max)
insert into _MigrationHistory(MigrationId,CreatedOn, Model, ProductVersion) values(...)
→ 執行:udb -verbose
此時與資料庫連接,執行語句
→ 如果想從某個一個遷移開始
udb -sourcemigration:"somename" -script
→ 執行: udb -verbose
關閉種子數據
Database.SetIntializer<SomeContext>(null);