Code First
Code First模式我們稱之為“代碼優先”模式,是從EF4.1開始建立加入的功能。使用Code First模式進行EF開發時開發人員只需要編寫對應的資料類(其實就是領域模型的實現過程),然後自動產生資料庫。這樣設計的好處在於我們可以針對概念性模型進行所有資料操作而不必關係資料的儲存關係,使我們可以更加自然的採用物件導向的方式進行面向資料的應用程式開發。
從某種角度來看,其實“Code First”和“Model First”區別並不是太明顯,只是它不藉助於實體資料模型設計器,而是直接通過編碼(資料類)方式設計實體模型(這也是為什麼最開始“Code First”被叫做“Code Only”的原因)。但是對於EF它的處理過程有所差別,例如我們使用Code First就不再需要EDM檔案,所有的映射通過“資料註解”和“fluent API”進行映射和配置。另外需要注意的是“Code First”並不代表一定就必須通過資料類來定義模型,事實上也可以通過現有資料庫產生資料類。
那麼我們首先看一下傳統的Code First如何使用。
首先建立一個控制台應用程式,接下來添加兩個類“Order”和“OrderDetail”,我們可以看到這兩個類只是簡單的C#對象(POCO,Plain Old C# Object)這兩個類基本和EF沒有任何關係,需要注意的是這兩個類有兩個導覽屬性“Order.OrderDetails”和“OrderDetail.Order”:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoEF{ class Order { public int Id { get; set; } public string Customer { get; set; } public System.DateTime OrderDate { get; set; } public virtual List<OrderDetail> OrderDetails { get; set; } }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoEF{ class OrderDetail { public int Id { get; set; } public string Product { get; set; } public string UnitPrice { get; set; } public int OrderId { get; set; } public virtual Order Order { get; set; } }}
有了這兩個類之後讓我們定義一個資料庫上下文,有了它我們就可以對資料進行增刪改查操作了,這個類必須繼承於"System.Data.Entity.DbContext”類以賦予它資料操作能力。因此接下來我們需要給這個應用安裝EntityFramework包,因為到目前為止我們並沒有引入EF架構相關的任何內容,我們需要引入EF相關程式集。但是我們有更好的選擇那就是NuGet。通過NuGet進行線上安裝:項目中右鍵選擇"Manage NuGet Packages…”;選擇Online;再選擇“EntityFramework”;然後點擊安裝即可。
資料庫上下文操作類:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoEF{ class Program { static void Main(string[] args) { using (var ctx = new OrderContext()) { var o = new Order(); o.OrderDate = DateTime.Now; ctx.Orders.Add(o); ctx.SaveChanges(); var query = from order in ctx.Orders select order; foreach (var q in query) { Console.WriteLine("OrderId:{0},OrderDate:{1}", q.Id, q.OrderDate); } Console.Read(); } } }}
運行結果:
如果是第一次使用EF Code First的朋友一定會有疑問,我們沒有進行任何資料庫配置,增加了一條資料通過查詢確實儲存上了,那麼我們的資料到底在哪呢。事實上如果使用者不進行資料庫配置EF預設會使用“.\SQLEXPRESS”資料庫執行個體,如果你沒有安裝“.\SQLEXPRESS”則預設使用LocalDb,關於LocalDb的具體細節請看:SQL Server 2012 Express LocalDB。我們可以在這裡找到系統自動建立的資料庫:
但是多數情況下我們是希望自己控制這個資料庫的,例如我想讓他儲存在我機器上的”.\SQL2008”執行個體上,此時我們就需要在設定檔App.Config中配置一個資料庫連接串,然後在我們的資料庫上下文中指定這個串連名稱。
App.config設定檔:
<?xml version="1.0" encoding="utf-8"?><configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <connectionStrings> <add name="CodeFirstDb" connectionString="Data Source=LENOVO\SQLEXPRESS;Database=CodeFirstDb;UID=sa;PWD=sql;" providerName="System.Data.SqlClient"></add> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework></configuration>
OrderContext類,建構函式多了一個串連名參數:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Data.Entity;namespace DemoEF{ class OrderContext:DbContext { public OrderContext(string connectionName) : base(connectionName) { } public DbSet<Order> Orders { get; set; } public DbSet<OrderDetail> OrderDetails { get; set; } }}
使用的時候,傳入配置的資料庫連接字串名稱:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoEF{ class Program { static void Main(string[] args) { using (var ctx = new OrderContext("CodeFirstDb")) { var o = new Order(); o.OrderDate = DateTime.Now; ctx.Orders.Add(o); ctx.SaveChanges(); var query = from order in ctx.Orders select order; foreach (var q in query) { Console.WriteLine("OrderId:{0},OrderDate:{1}", q.Id, q.OrderDate); } Console.Read(); } } }}
執行之後就會發現在”.\sqlexpress”執行個體上多了一個“CodeFirstDb”資料庫(注意圖中除了我們建立的兩個實體表還有一個系統資料表dbo._MigrationHistory它記錄了模型的定義,在以後的文章中我會著重解釋此表):