Entity Framework Migration Essential

使用 Entity Framework 的 Code First 來做資料存取層與既存資料庫溝通時多少都會遇到資料庫 Schema 變更的時候,只是這個時候若是有用到 Code First 來新增表格的話就會遇到像上一篇一樣的問題;執行時期使用資料庫的話會引發錯誤訊息,而且會通知因為資料庫的 Schema 變更需要使用 Migrations 來解決問題。因此這篇文章就是要來說明一般來說使用 Code First 來開發遇到資料庫 Schema 要變更時的正規作法應該怎麼做。 我們就用上一篇所生出來的資料庫來實作看看吧~ 不過為了方便起見,我們就直接先把 Products 這個資料表先刪除,我們來看看用 Code First 的方式開發的話若要新增一個資料表的正規方式是什麼?(這邊正規也只是我在講而已,只是這麼做的話可以免除之後的麻煩) 首先我們要先打開套件管理員的命令列視窗「Tools => Library Package Manager => Package Manager Console」,然後要用 Migrations 的話就要先把功能打開,需要下這樣的指令: 1 PM >> Enable-Migrations ,成功的同時我們的專案會新增一個 Migrations 資料夾,並且會給你一個 Configrations.cs 類別,若沒有要使用自動 Migrations 的話就可以先不用動這個類別的內容。接下來因為需求異動的關係我們需要多一個 Products 資料表來儲存產品的資訊。 Products 的資料表如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /// 產品的實體。 [Table("Products")] public class Product { /// 產品的識別號。 [Key] [ScaffoldColumn(false)] public int ID { get; set; } /// 產品的名稱。 public string Name { get; set; } /// 產品的價格。 public double Price { get; set; } /// 生產產品的工廠名稱。 public string FactoryName { get; set; } } 對於資料庫的 Schema 的異動我們可以在 Package Manager Console 中輸入 Add-Migrations xxxxxx xxxxxx就是新增的類別的名稱,通常會是這次異動的表格、欄位的名稱像是 AddProducts 之類的。這邊我是用 AddTableProducts ...

November 20, 2012 · 3 分鐘 · 427 字

EF Code First With Existing DataBase Modify Column

話說之前那一篇的 Entity Framework 觀念其實還是有很多地方是不大清楚的,像是使用 Code First with existing database 時什麼情況會異動到資料庫?什麼情況下需要做 Migrations?什麼情況下會直接吐個 Exception 給你而不是自動幫你多個 Table 或 Column?,所以今天就趁著一點時間來寫一下從接觸至今的處理經驗了…(說的好像經驗老到其實還是個新手) 前置工作 這次的範例中我們會需要一個無辜的資料庫讓我們(恣意蹂躪)測試。 就讓我們把這個偉大的資料庫命名為…Demo! 唔…其實 Products 先不用建起來,我們可以來做個實驗看看什麼時候會觸發 Migrations…好~建立起這個資料庫之後我們就可以馬上來寫 Code 玩玩看啦~! 這裡我們就使用 Console Application 就好。我們建立一個名為 EFMigrationDemo 的專案,並在根目錄處新增一個 Model 資料夾裡面放置我們最重要的類別。 在寫 Code 之前我們要先把 EntityFramework 裝起來~就直接打開 Package Manager Console 吧!請在 Console 中直接輸入: Install-Package EntityFramework 若不放心是否為最新就接著下: Update-Package EntityFramework 這樣就可以保證你所指定的套件是最新的! 前置工作這樣就算是告一段落了~ 寫 Code 囉 我們新增一個類別檔案於 Model 資料夾中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 using System.Data.Entity; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace EFMigrationDemo.Model { public class Customers // 類別名稱與資料庫中的表格名稱一樣 { // 標記該屬性(在資料庫中為欄位)為 Promary key //(若屬性結尾為 ID 依照 Conversion naming 規則 EF 會自己判斷出來) [Key] public int ID { get; set; } // 標記該欄位是不能為Null的 [Required] public string Name { get; set; } [Required] public string Address { get; set; } [Required] public string PhoneNumber { get; set; } [Required] public string Email { get; set; } // 標記這個屬性對應到資料庫中的欄位名稱為 NickName 而非 TheNickName // 而且該欄位的內容長度不超過50 [Column("NickName")] [MaxLength(50, ErrorMessage = "Your Nick Name too long")] public string TheNickName { get; set; } // 標記這個屬性並不會對應到資料庫中的任何欄位 [NotMapped] public string NameplusNickName { get { return Name + NickName; } } // 這是個類別所以還是可以有方法,而且不會被認為是欄位或是預儲程序 public void PrintName() { Console.WriteLine("My name is {0}", this.Name); } } // 繼承 DbContext 的類別可以當成是資料庫來進行操作,預設會去 Config 檔中抓取 connectionString 的 section 裡與類別名稱相同的項目,像是: // <add name="Demo" connectionString="" providerName=""> // 而類別名稱其實也可以不用跟資料庫名稱一樣 public class Demo : DbContext { // 被 DbSet 包起來的類別會被判定為是一個實體(也就是一個表格) // 所以屬性名稱並不會影響到表格名稱 public DbSet<Customers> Customer { get; set; } } } 這樣我們的 Model 類別就算準備好了,接下來就是準備呼叫端了~ ...

November 16, 2012 · 3 分鐘 · 566 字

EF-With-Repository-Pattern

在上一篇中我們有使用到一個 NorthwindReposity 類別來存取資料庫,不過我們也發現到這樣的寫法與呼叫端的耦合度還是有點高。若我要使用的資料所要做的事情是固定的,像是瀏覽產品資訊時的產品資料是從主資料庫中找到產品的資料表並取出指定產品的資料,那麼其實對這個部分來說其實他就只關心產品得資料如何存取和操作而已。一個簡單的想法是,我們讓呼叫端用一個介面來針對他所感興趣的部份去做操作。 實作 我們用的資料庫依然是北風資料庫,而且和上一篇是一樣的!避免頁面切來切去這邊就直接寫囉~ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 using System.Data.Entity; using System.ComponentModel.DataAnnotations.Schema; public class Northwind : DbContext { public DbSet<product> Products { get; set; } public DbSet<category> Categories { get; set; } } public class Product { public int ProductID { get; set; } public string ProductName { get; set; } public Decimal? UnitPrice { get; set; } public bool Discontinued { get; set; } [ForeignKey("Category")] public int CategoryID { get; set; } public virtual Category Category { get; set; } } public class Category { public int CategoryID { get; set; } public string CategoryName { get; set; } public string Description { get; set; } public byte[] Picture { get; set; } public virtual ICollection<product> Products { get; set; } } 接下來就是我們上一篇用來存取資料庫的主要類別,也是我們這次的修改標的物。 ...

November 8, 2012 · 4 分鐘 · 721 字

EF Code First With Existing Database

在開發專案時很多時候若有連接到資料庫,通常會把 Model 這個部分先切割出來開發,這樣可以讓 Model 獨立在主 project 之外讓其他 projects 可以一起使用,在維護的時候其實也會比較方便只需要抽換DLL就好(這也算關注點分離嗎),另外就是 Model 天生就比較能夠獨立出來開發。不過在獨立開發 Model 的時候也要注意一些小東西。今天使用 Entity Framework (version 5) 的 Code First with existing database 的方式來做個示範。 實作部分 我們選用的 Database 是赫赫有名的 Northwind 資料庫,我想這個資料庫大家應該都比我還熟了。這次我們選出 Products 和 Categories 這兩個資料表來做示範的 Table 吧~!順便提醒一下用 Code First with existing database 時會有些小地方需要注意! 首先~我們就來把 Northwind database bring online 吧~ 把資料庫 online 後,接下來就切到 Visual Studio 中創一個新的 Class Library 專案吧~ 專案名稱就隨便給個 Project.Model 來代表這個 DLL 是我們的 Model。而因為要用 Entity Framework 的 Code First 功能,我們要引用一個 EF 的 DLL:EntityFramework,若是用 Nuget 來安裝的話會連同 System.Data.Entity 這個 DLL 一起裝,不過若是沒有要用視覺設計工具來輔助的話其實是可以不用這個 DLL 的。 ...

October 5, 2012 · 3 分鐘 · 464 字