實體框架Entity Framework 4.1快速入門
介 紹
在舊的Entity 框架中,開發者可以從已存在的資料庫中產生業務實體的模型,這種開發方法被稱為資料庫驅動的開發方法。而在4.1的Entity Framework中,支開發者先建立實體業務類,然後再產生相關的資料庫檔案,這種開發方法可以稱為“程式碼先行”的開發方法。這種方法對於開發者來說是很有好處的,首先,會讓開發者從面向物件的思維角度出發,去構建業務邏輯中的實體模型,然後再根據實際的需要去生成資料庫檔案,是真正的面向物件的思維開發方法。
本文中要使用Entity Framework 4.1,這裡提供下載該框架安裝程式:。
同時,VS.NET 2010也是少不了的,而本文的配套程式碼,可以在這裡下載:。
本文的例子將會建立兩個類Invoice類和LineItem類。而本文產生的資料庫命名為Accounting,並會產生兩張表:Invoice和LineItem。例子中的功能,還包括可以在gridview中對資料庫中的資料進行增刪改查,最後,還會演示如果類發生了變化了,如何讓相應的資料庫也發生改變。
步驟1
1) 啟動vs.net 2010;
2) 新建立一個c#語言的asp.net web工程專案;
3) 將工程命名為project EF4CodeFirst;
4) 在工程資源管理器中,滑鼠右鍵點選,然後新增一個類,將新增的類命名為Invoice.cs。
修改這個類的程式碼如下:
{
public int ID { get; set; }
public DateTime InvoiceDate { get; set; }
public double Total { get; set; }
}
在我們的類中,有id這個屬性,Entity框架會根據id這個屬性,去生成資料庫表中的對應欄位id,如果類中沒定義id這個屬性,則會在資料庫表文件中生成以“類檔名+ID”這樣命名的欄位。
在這個Invoice發票類中,存在多個條目LineItem,它們之間明顯構成一對多的關係,所以我們先建立類LineItem類。
5) 同樣,新增一個LineItem類,程式碼如下:
public class LineItem{
public int ID { get; set; }
public string ProductName { get; set; }
public double ItemCost { get; set; }
public double Units { get; set; }
public Invoice Invoice { get; set; }
}
在這個類中,維持了對Invoice類的引用,同時也是關聯了Invoice類。
6)而在Invoice類中,也要增加LineItem類的引用,這裡要用到的是集合類,如下程式碼:
public ICollection<LineItem> LineItems { get; set; }同時要在Invovice類的建構函式中,進行初始化LineItem類,如下:
public Invoice(){
LineItems = new List<LineItem>();
}
在完成上面的步驟後,則Entity框架已可以從實體類中建立相關的資料庫和表了,下面繼續進行步驟二。
步驟2
接下來,我們要引用Entity框架的類庫檔案到我們的工程中。
1) 在工程資源管理器中,滑鼠右鍵點選工程名字,在彈出的選單中選擇“新增引用”。
2) 在出現的如下圖的介面中,選擇System.Data.Entity ,並點確定完成:
3) 為工程繼續增加一個新類,命名為Accounting.cs ,並且修改其程式碼如下:
using System.Data.Entity;public class Accounting : DbContext
{
public DbSet<Invoice> Invoices { get; set; }
public DbSet<LineItem> LineItems { get; set; }
}
可以看到,該類繼承了DbContext類,該類實際上是Entity的一個工具類,裡面封裝了很多有用的API,在Accounting類中,分別有兩個DbSet類的例項,它們代表將要在資料庫中生成的兩個表。
4)接著需要在web.config中進行新增資料庫連線,如下:
<add name="Accounting"providerName="System.Data.SqlClient"
connectionString="Data Source=(local);Initial Catalog=Accounting;Integrated Security=SSPI;"/>
5) 接著,在default.aspx 中新增gridview控制元件,並且編寫如下程式碼:
using System.Data.Entity;protected void Page_Load(object sender, EventArgs e)
{
Accounting db = new Accounting();
db.Invoices.Load();
GridView1.DataSource = db.Invoices.Local.ToBindingList();
GridView1.DataBind();
}
記得這裡必須引入System.Data.Entity類庫,並且例項化Accounting物件的例項db,並呼叫其load方法,載入所有的Invoice資料(這裡我們一般是載入一對多的一方的資料)。
6)執行工程後,你會發現在SQL SERVER中,會出現了三張表,如下圖:
其中,分別是Invoice表和LineItem表,還有一張表EdmMetadata,是Entity框架為我們自動生成的,儲存了資料庫中的元資料。另外,可以看到在表LineItem中,Entity框架已經為我們自動生成了外來鍵Invoice_ID,如下圖:
步驟三
現在,既然資料庫已經建立了,則可以為其增加一些資料了,在page_load中增加如下程式碼:
protected void Page_Load(object sender, EventArgs e){
Accounting db = new Accounting();
Invoice invoice = new Invoice
{
InvoiceDate = DateTime.Now,
Total = 1000
};
db.Invoices.Add(invoice);
db.SaveChanges();
db.Invoices.Load();
GridView1.DataSource = db.Invoices.Local.ToBindingList();
GridView1.DataBind();
}
在這裡我們例項化了Invoice類的一個例項,添加了相關的資料內容,然後使用db.Invoices.Add增加到Account類的DBSet屬性中,最後呼叫savechanges方法儲存到資料庫中,執行後,可以看到如下效果:
現在我們試下更新資料,程式碼如下:
protected void Page_Load(object sender, EventArgs e){
Accounting db = new Accounting();
Invoice invoice = new Invoice
{
ID = 1,
InvoiceDate = DateTime.Now,
Total = 900
};
db.Entry(invoice).State = EntityState.Modified;
db.SaveChanges();
db.Invoices.Load();
GridView1.DataSource = db.Invoices.Local.ToBindingList();
GridView1.DataBind();
}
這裡把invoice例項的成員變數的ID改為1,注意在更新時,設定其狀態(state)為EntityState.Modified,表示是修改記錄,最後再儲存,執行後,可以看到資料庫中的資料的確更新了,所有這些都是Entity 框架在起作用。
最後學習刪除記錄,程式碼如下:
protected void Page_Load(object sender, EventArgs e){
Accounting db = new Accounting();
Invoice invoice = new Invoice
{
ID = 1,
InvoiceDate = DateTime.Now,
Total = 900
};
db.Invoices.Remove(invoice);
db.SaveChanges();
db.Invoices.Load();
GridView1.DataSource = db.Invoices.Local.ToBindingList();
GridView1.DataBind();
}
這裡只需要呼叫Remove方法,即可在資料庫中刪除該記錄。
步驟4
在這個步驟中,我們學習如何改變資料模型。假設我們要在Invoice類中增加一個Tax的屬性,也需要Entity框架同步在資料庫中增加這個欄位,下面演示其步驟:
1)我們在Invoice類中增加Tax這個屬性。
2)如果這時執行工程,則會看到如下的錯誤提示:
The model backing the 'Accounting' context has changed since the database wascreated. Either manually delete/update the database, or call
Database.SetInitializer with an IDatabaseInitializer instance. For example, the
DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate
the database, and optionally seed it with new data.
提示告訴我們,或者這個時候重新手工刪除資料庫或者使用程式碼的方法去完成,我們使用程式碼的方法去完成,只需要在Application_Start事件中編碼如下,即可讓Entity框架,自動把新增加的屬性反映到資料庫中:
void Application_Start(object sender, EventArgs e){
// Code that runs on application startupSystem.Data.Entity.Database.SetInitializer<Accounting>
(new System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting>());
}
3) 再次執行工程,會看到資料表中的確增加了Tax這個欄位了,如下圖:
步驟5
注意,在上面的步驟4中,如果類的屬性發生變化,則其實是通過程式碼的方法,重新將舊的資料庫DROP掉,然後再新建,這樣的話費時費力,而可以通過另外的一個方法實現,即還好我們可以在初始化的過程中新增測試資料,這樣每次重新建立資料庫的時候,測試資料就會自動加進去了,算是解決了一些問題,方法如下:
1)在工程專案中,新增加一個類,命名為AccountingInitializer.cs
2)修改其程式碼如下:
public class AccountingInitializer :System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting>
{
protected override void Seed(Accounting context)
{
Invoice invoice = new Invoice { Total = 20, InvoiceDate =
new DateTime(2011, 4, 14), Tax = 1.50 };
invoice.LineItems.Add(new LineItem
{ ItemCost = 2, ProductName = "Test", Units = 4 });
invoice.LineItems.Add(new LineItem
{ ItemCost = 4, ProductName = "Test 2", Units = 3 });
context.Invoices.Add(invoice);
context.SaveChanges();
base.Seed(context);
}
}
其中,在這個類中繼承了DropCreateDatabaseIfModelChanges這個類,並且重寫了seed這個方法,在這個方法中可以編寫新增測試資料。要記得還需要在Application_OnStart事件中編寫如下程式碼:
void Application_Start(object sender, EventArgs e){
//在啟動過程中執行該段程式碼 System.Data.Entity.Database.SetInitializer<Accounting>
(new AccountingInitializer());
}
小 結
可以看到,Entity Framework 4.1的確方便了使用者的開發操作,能讓使用者更專注於業務邏輯實體的開發,更符合OOP的思維方式,更多關於Entity Framework的操作,請參考微軟的MSDN。