初识Entity Framework CodeFirst(2)
上一回合,我們討論了如何簡單的使用Entity Framework CodeFirst功能。
結尾的時候,我們提出了一個有趣的問題,如果我們的數據實體需要發生變化呢?需要添加多一個Model類呢?修改已有實體中字段呢?我們該怎么辦?該不會是把數據庫刪掉,然后讓程序重新生成吧?很明顯,答案當然不是啦。EF作為微軟推薦的框架之一,沒有這么差勁的。
本節,我們討論一下內容:
1、Migration控制臺
2、修改已有實體,添加/刪除 數據庫字段
3、添加新實體模型與數據庫表映射
4、修改實體屬性與數據庫字段名映射
代碼點擊這里下載
1、打開程序包管理器控制臺,并啟動Migrations (遷移)
方法如下:點擊工具->庫程序包管理器->程序包管理器控制臺
在控制臺中輸入“Enable-Migrations” (小技巧:這里支持Tab自動補全),啟動Migrations。
這時候,項目解決方案處會多出一個文件夾“Migrations”以及其下級的文件
“Configuration.cs”文件包含本項目CodeFirst的基本配置,一般情況下我們大可不必修改里面的內容。
201303241026370_InitialCreate public partial class InitialCreate : DbMigration{public override void Up(){CreateTable("dbo.Blogs",c => new{BlogID = c.Int(nullable: false, identity: true),BlogName = c.String(),}).PrimaryKey(t => t.BlogID);CreateTable("dbo.Posts",c => new{PostID = c.Int(nullable: false, identity: true),Title = c.String(),Content = c.String(),BlogID = c.Int(nullable: false),}).PrimaryKey(t => t.PostID).ForeignKey("dbo.Blogs", t => t.BlogID, cascadeDelete: true).Index(t => t.BlogID);}public override void Down(){DropIndex("dbo.Posts", new[] { "BlogID" });DropForeignKey("dbo.Posts", "BlogID", "dbo.Blogs");DropTable("dbo.Posts");DropTable("dbo.Blogs");}}“201303241026370_InitialCreate.cs”(命名有系統自動生成)包含的則是初始化語句。大家可以看到里面包含了兩個方法,一個是Up,用于初始化時建立數據庫(表);另外一個則是Down,刪除數據庫(表)的。
我們必須借助Migrations 來對實體類中的修改更新到數據庫的結構當中。
?
2、如何修改已有實體(實例:在已有model中添加一個字段)
舉個例子(還是來自于MSDN),我們對Blog Model進行修改,添加一個“Url”的字段
class Blog{public int BlogID { get; set; }public string BlogName { get; set; }public string Url { get; set; }}打開Migration控制臺,輸入“Add-Migration AddUrl”,這時我們發現解決方案中多了一個文件,名為:201303241155123_AddUrl
該文件產生的代碼如下:
AddUrl public partial class AddUrl : DbMigration{public override void Up(){AddColumn("dbo.Blogs", "Url", c => c.String());}public override void Down(){DropColumn("dbo.Blogs", "Url");}}再在Migration控制臺輸入:“Update-Database”,更新數據庫結構。
新增的字段就乖乖的新建出來了。
這里解析一下:
(1)、Migration控制臺中,“Add-Migration XXX”,其中的XXX為各位讀者自己命名,可以起任意的名字,這里還是建議各位讀者朋友名一個有實意的名字以方便后續的工作。
(2)、生成的新代碼中,它繼承自DbMigration,里面包含了兩個重寫方法,UP和Down,Up中調用了AddColumn方法插入新字段,傳入三個參數,分別是“表名”、“字段名”以及一個用于確定數據類型的lambda表達式;Drow方法則調用DropColumn,傳入“表名”和“字段名”來刪除該字段。有興趣的同學可以對DbMigration進行反編譯,可以看到里面包含的所有方法。
?
3、新增一個實體(實例:添加一個Type Model和一個User Model)
3.1、添加一個Type實體
class Type{public int TypeID { get; set; }public string TypeName { get; set; }}修改上下文BlogContext,添加一個Types屬性
class BlogContext:DbContext{public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }public DbSet<Type> Types { get; set; }}調出Migration控制臺,“Add-Migration AddType”——>“Update-Database” ,很好,Type表已經輕松的生成。
3.2、添加一個User Model
各位讀者有沒有發現,之前我們一直新建的實體,實體字段第一位都是XXID(總是int類型),這里我們做一點改動,不要XXID,只要UserName和DisplayName兩個string類型的字段。
添加Model
class User{public string UserName { get; set; }public string DisplayName { get; set; }}修改上下文
class BlogContext:DbContext{public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }public DbSet<Type> Types { get; set; }public DbSet<User> Users { get; set; }}我們還像以往一樣,調出Migration控制臺,然后執行“Add-Migration AddUser”——>“Update-Database”
聰明的讀者一定會猜得出后果會怎么樣,沒錯,這回報錯了,報錯內容為:沒有找到主鍵
這時,我們需要在User中手動添加一個主鍵的標簽
class User{[System.ComponentModel.DataAnnotations.Key]public string UserName { get; set; }public string DisplayName { get; set; }}重新調出Migration控制臺,“Add-Migration AddUser”——>“Update-Database”
通過,User表已經生成在數據庫中。
這時,我們或許會產生或多或少的暗示——不指定主鍵的時候,EF默認會自動的幫我們指定。
這里,我把Type實體和User實體通過調用Migration生成的兩個Add文件的代碼貼出來。
AddType public partial class AddType : DbMigration{public override void Up(){CreateTable("dbo.Types",c => new{TypeID = c.Int(nullable: false, identity: true),TypeName = c.String(),}).PrimaryKey(t => t.TypeID);}public override void Down(){DropTable("dbo.Types");}} AddUser public partial class AddUser : DbMigration{public override void Up(){CreateTable("dbo.Users",c => new{UserName = c.String(nullable: false, maxLength: 128),DisplayName = c.String(),}).PrimaryKey(t => t.UserName);}public override void Down(){DropTable("dbo.Users");}}對比一下,答案也許各位讀者已經找到了。沒錯,答案就在重寫的UP中,各位是否發現,沒有指明主鍵的Type實體中,EF會自動的把第一個字段指定為identity(自增)的int型主鍵,當然,前提必須為這個被指定的字段在model中的屬性為int類型。而在User實體中,全部都是string類型的屬性,因為EF無法通過默認的方式找到可以自動添加的主鍵字段,所以Migrants控制臺想Add-Migrants時就會發生內容為:找不到主鍵的報錯啦。
這里我需要補充一下,精明的讀者也許發現,通過CodeFirst生成的數據表中,字段的類型也只能確定個大概,并不能進行比較精確的確定,比如通過string類型屬性反向生成的字段,其字段容量大小竟然為“Max”;其實,在“Update-Database”之前,我們可以通過對“Add-Migration”中生成的Add文件(暫時想不出有什么方法形容這些文件)中的UP方法進行細小的微調,然后再執行“Update-Database”,我們就可以生成真正想要字段大小啦。
?
3、修改已存在的實體,數據庫中對應字段的字段名
有時候,我們已經使用EF CodeFirst對數據庫已經進行了反向的生成,但是,我們又想修改一下數據庫中,與實體屬性對應的某個字段的字段名,這個時候我們應該怎么辦呢?
這里,我們只需要在上下文中override一個方法
class BlogContext:DbContext{public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }public DbSet<Type> Types { get; set; }public DbSet<User> Users { get; set; }protected override void OnModelCreating(DbModelBuilder modelBuilder){modelBuilder.Entity<User>().Property(u => u.DisplayName).HasColumnName("Display_Name");}}在Migration中,“Add-Migration”——>“Update-Migration”
好的,O了。
這節我們已經討論完畢了,各位讀者如果有什么更好的建議或者意見,歡迎留言。
?
?
轉載于:https://www.cnblogs.com/xiaodiejinghong/archive/2013/03/24/2979924.html
總結
以上是生活随笔為你收集整理的初识Entity Framework CodeFirst(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谈谈技术文档的编写
- 下一篇: 奇怪的匿名函数之争EventHandle