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它記錄了模型的定義,在以后的文章中我會着重解釋此表):