在上一篇【數據庫遷移利器:Migrator.Net】中,很多朋友提到了EF的CodeFirst也有數據庫的遷移功能,說來真慚愧,玩了那么多年,至今還未去了解EF,今天來了解下CodeFirst然后與Migrator.Net進行下橫向對比。
CodeFirst是EF提供的一種技術手段,使我們從以往的創建數據庫后再創建模型變成了只需要關注代碼方式進行創模,然后通過EF框架映射到數據庫架構並生成。
CodeFirst除了創建新數據庫之外,還提供了相應的遷移工具,通過升級和回滾操作相應的更新我們的數據庫架構。這些方面都跟我之前介紹的Migrator.Net有異曲同工的作用。
創建新數據庫並生成初始架構
通過NuGet直接引用EntityFramework,看下以下代碼:
public class BlogContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } } public class Blog { public Blog() { Posts = new List<Post>(); } public int BlogId { get; set; } public string Name { get; set; } public virtual IEnumerable<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public virtual Blog Blog { get; set; } }
我們創建了Blog和Post模型,通過在BlogContext中注冊這2個模型,通過以下代碼:
class Program { static void Main(string[] args) { using (var db = new BlogContext()) { db.Database.Initialize(true); } Console.WriteLine("Press any key to exit..."); Console.Read(); } }
運行程序后,我們來看下數據庫的變化。這里要說下,在我們數據庫連接都沒有配置的情況下,默認情況下VS2012使用LocalDB,VS2010使用SqlExpress。LocalDB不支持SqlServer Management Studio進行連接。
使用VS2012的數據連接,我們能看到我們的數據庫已經創建,數據庫名為命名空間.Context名,這里是CodeFirstMigrator.BlogContext
Blogs和Posts表就是EF為我們創建的2個模型表,_MigrationHistory就是版本的信息
_MigrationHistory表與Migrator.Net的SchemaInfo表類似,都保存着版本信息,不過_MigrationHistory存儲的數據更多一些。
更新表字段
我們為Blog模型添加一個Url屬性,然后再運行程序,我們發現會報錯:
CodeFirst默認情況下,只能為重新創建數據庫和表,並不能更新已存在的數據庫,我們必須使用CodeFrist的Migrations功能創建遷移版本,再去更新數據庫。
首先需要為Context創建遷移
在程序包管理控制台中運行:Enable-Migrations
運行后,會在我們的項目解決方案中生成Migrations目錄
InitialCreate.cs就是我們初始需要創建的腳本,Configuration是一些遷移配置。我們看下InitialCreate的代碼:
public partial class InitialCreate : DbMigration { public override void Up() { CreateTable( "dbo.Blogs", c => new { BlogId = c.Int(nullable: false, identity: true), Name = c.String(), }) .PrimaryKey(t => t.BlogId); CreateTable( "dbo.Posts", c => new { PostId = c.Int(nullable: false, identity: true), Title = c.String(), Content = c.String(), Blog_BlogId = c.Int(), }) .PrimaryKey(t => t.PostId) .ForeignKey("dbo.Blogs", t => t.Blog_BlogId) .Index(t => t.Blog_BlogId); } public override void Down() { DropForeignKey("dbo.Posts", "Blog_BlogId", "dbo.Blogs"); DropIndex("dbo.Posts", new[] { "Blog_BlogId" }); DropTable("dbo.Posts"); DropTable("dbo.Blogs"); } }
發覺了沒,跟Migrator.Net及其相像,通過繼承DBMigrator類,重寫Up和Down方法實現升級或者回滾的響應操作。
回到之前更新的操作,我們使用程序包控制台程序輸入:Add-Migration AddBlogUrl
紅色為版本命名,需要唯一。
我們在控制台再輸入:Update-Database
通過Update-Database后,會更新我們的數據庫架構,如圖:
響應的Blogs表 和_MigrationHistory表都會有所變化。
遷移到特定版本(回滾)
CodeFirst通過控制台輸入Update-Database –TargetMigration: 版本名稱 進行指定版本的遷移,例如我們回滾到初始創建時:Update-Database –TargetMigration:InitialCreate
我們不需要切換到cmd控制台,直接在VS中就能進行操作,這點還是很方便的。
其他環境進行遷移操作
如果需要再其他開發環境中搭建數據庫的話,只需要獲取最新的項目代碼,使用Update-DataBase命令就可以了。如果需要實踐到應用環境,則需要通過Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: 版本名稱 生成Sql腳本,提供給DBA進行數據庫操作。
您也可以在項目運行開始添加如下操作:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());
與Migrator.Net對比
作為數據庫遷移工具來講,大家都差不多,都能實現數據庫架構的遷移,原理也很相近,不過CodeFirst因為是含在EF中,有了微軟的支持在VS中使用,而且遷移代碼都是自動生成,這個方面大大提高了開發進度。而Migrator.Net一般會新建一個類庫,專門作為遷移用,但因為遷移代碼都是我們自己完成,所以對碼農來說會更新明了。如果數據庫復雜度不高的話,隨便用哪個都可以,但一般我們的項目會越來越龐大,數據庫的更改也會越來越頻繁,這時候CodeFirst就會落后於Migrator.Net,CodeFirst會根據您控制台命令Add-Migration生成從之前版本到現在的所有更改,而Migrator.Net則因為我們自己來編寫的,會清晰明了,對遷移來說也會更好(個人想法,可能還未深入了解的關系吧)。
CodeFirst |
Migrator.Net |
|
數據庫類型支持 |
默認支持SqlServer,LocalDB,SqlExpress |
默認支持:MSSQL,MySql,Sqlite,oracle,PostgreSql |
與VS集成 |
集成度高 |
無集成 |
遷移工具 |
通過生成SQL腳本 |
通過命令行遷移 |
復雜度 |
開發簡單,遷移腳本自動生成 |
開發一般,遷移腳本自己編寫 |
項目耦合度 |
耦合度高,因為是自動生成遷移腳本,需要依賴實體類和上下文。 |
無耦合,遷移腳本自己編寫,不需要了解我們的實體類 |
數據庫特性支持 |
基本支持,遇到特別字段,可通過修改生成的遷移腳本進行修改 |
基本支持 |
創建新數據庫 |
可自動創建 |
需手動創建 |
兩個功能相似,但在使用上還是各有千秋,做為一個架構師來說,我更偏向於使用Migrator.Net,因為CodeFirst是EF的一種功能,我們的項目有時候不是必須使用EF的。
EF發展到現在已經到6.1版本,肯定已經很強大了,但種種原因至今還未接觸過,不知其強大的功能,今后有機會還是希望接觸一下。
CodeFirst 參考資料:
Migrate.exe