項目中用到了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);