[ASP.NET MVC 小牛之路]06 - 使用 Entity Framework

來源:互聯網
上載者:User

[ASP.NET
MVC 小牛之路]06 - 使用 Entity Framework

在家閑著也是閑著,繼續寫我的[ASP.NET MVC 小牛之路]系列吧。在該系列的上一篇博文中,在顯示書本資訊列表的時候,我們是在程式碼中手工造的資料。本文將示範如何在ASP.NET MVC中使用Entity
Framework從資料庫中擷取資料。雖然本文題目聽上去比較簡單,但如果你認真閱讀,相信你一定會有所收穫。

本文目錄:


ORM 和 EF

當我們要開發一個應用程式,就要考慮怎樣展示資料,怎樣持久化資料。考慮這個問題時我們所要關心的東西,最重要的莫過於程式的效能、開發的簡易性和代碼的可維護、可擴充性。

持久化(Persistence),是指在應用程式中能永久地儲存各個處理狀態資訊的機制。如果沒有持久化這個機制,狀態只能儲存在記憶體中,機器關機後就會丟失。

在應用程式中,當要永久地儲存資料時,我們會選擇關聯式資料庫(Relation DataBase);當要臨時地儲存資料時,我們則使用儲存在記憶體中的對象。目前對於大多數開發人員來說,都是用關聯式資料庫技術來作為持久化機制。雖然現在有些人正在嘗試使用對象資料庫(Object DataBase)技術,但關聯式資料庫技術在許多年以內依然會是最主要的持久化機制。

為什麼會出現對象資料庫? SQL語言是一種非過程化的面向集合的解釋型語言,而很多進階語言是過程化的物件導向的編譯型語言,這使得兩種語言之間存在著不匹配,導致效率不如人意。這種不匹配被稱為“阻抗失配”,對象資料庫的出現就是為瞭解決“阻抗失配”。

我們知道,在關聯式資料庫技術中是用Table以行和列的結構來存放和組織資料的。在.NET 2.0以前,C#還沒有泛型的時候,人們基本上用填充在DataSet中的DataTable來映射並存放從關聯式資料庫中查詢出來的資料,正如下面代碼所示:

using (SqlConnection conn = new SqlConnection(connString)) {    using (SqlDataAdapter da = new SqlDataAdapter("Select * from order", conn)) {        DataTable dt = new DataTable();        da.Fill(dt);        ...    }}

這種方式雖然能讓物件導向語言匹配關聯式資料庫,但它有一些明顯的缺點,如非型別安全、難操控、低效能等。從.NET 2.0開始,人們開始通過泛型技術用實體模型對象的集合來匹配關聯式資料庫中的資料,這種方式解決了DataTable方式所面臨的缺點,且它有強型別、在VS中自動完成、編譯時間檢查等特點,廠受.Net開發人員的喜愛。

為了讓開發人員不用手動去做這種“匹配”工作,人們研發了很多ORM工具(如Entity Framework、NHibernate等)。ORM(Object Relation Mapping)工具,顧名思義,它的角色就是為瞭解決“關係”和“物件導向”之間的“失配”,它可以使得開發人員不用過多關心持久層而可以花更多的時間專註於業務。

Entity Framework(EF)是微軟以ADO.NET為基礎所發展出來的ORM解決方案,以Entity Data Model(EDM) 為主。EF利用了抽象化資料結構的方式,將每個資料庫物件都轉換成應用程式中的類對象(Entity),而資料欄位都轉換為屬性 (Property),關係則轉換為結合屬性 (Association),讓資料庫的 E/R
模型完全的轉成物件模型,如此讓開發人員就能用熟悉的物件導向程式設計語言來調用訪問。EF 4.0 以後支援Database First、Model First、Code First三種產生模式,Code First模式用的人比較多。

概念和理論性的東西就不多講了,我也是帶著疑問去尋找網路資源根據自己的理解半摘半歸納出來的,而且鄙人不才,很多東西想描述但都不知道怎麼組織語言。

本文目的主要是讓讀者對EF有個感性的認識,然後瞭解EF在ASP.NET MVC中的應用,不會去研究原理性的東西,下次有空再單獨介紹EF吧。

使用Entity Framework

接著上一篇博文[ASP.NET
MVC 小牛之路]05 - 使用Ninject,我們現在要把代碼中手工造的資料改成從資料庫讀取。為此,我們先準備下資料庫。本樣本使用的是MS SQL Server,使用其他資料庫也是一樣的。先建立一個名為BookShop的資料庫,然後執行下面的指令碼建立一個Books表:

CREATE TABLE Books (     [ID] INT NOT NULL PRIMARY KEY IDENTITY,     [Title] NVARCHAR(100) NOT NULL,    [Isbn] VARCHAR(20) NOT NULL,     [Summary] NVARCHAR(1000) NOT NULL,    [Author] NVARCHAR(50) NOT NULL,    [Thumbnail] VARBINARY(MAX),      [Price] DECIMAL(16, 2) NOT NULL,    [Published] DATE NOT NULL,)

然後隨便在表中加幾條用於測試的資料:

接下來我們就要讓應用程式串連資料庫了。由於上一篇博文是我在公司用休息的時間寫的,公司的電腦裝的是VS2010,家裡的筆記本裝的是VS2012,所以得重新把上篇博文的樣本移到VS2012上,對於本樣本,VS2010和VS2012都是一樣的。上一篇樣本項目的目錄結構如下:

本文的樣本將在上篇的這個樣本基礎上繼續。

用NuGet在BookShop.Domain工程中安裝Entity Framework包,方法請參考本系列的上一篇文章。

在BookShop.Domain工程的Concrete檔案夾中添加一個名為EFDbContext的類,代碼如下:

public class EFDbContext : DbContext {     public DbSet<Book> Books { get; set; } }

使用EF Code First第一步就是建立一個繼承自System.Data.Entity.DbContext的類,這個類將為資料庫中的每個表定義一個屬性,屬性的名稱代表資料庫中的表名。DbSet作為傳回型別,它是用於產生CRUD(Create、Read、Update和Delete)操作的裝置,映射資料庫表的行。

我們需要在BookShop.WebUI工程中的web.config設定檔中添加資料庫的連接字串,來告訴EF怎樣串連資料庫。根據自己機器上的資料庫配置連接字串如下:

<connectionStrings>  <add name="EFDbContext" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=BookShop;User ID=sa;Password=sa" providerName="System.Data.SqlClient" /></connectionStrings>

接下來,我們把BookShop.Domain工程下Concrete檔案中的BookRepository類檔案改造一下,把代碼中手工造的資料改成從資料庫讀取,以測試應用程式是否可以正常串連資料庫。修改後的BookRepository類如下:

public class BookRepository : IBookRepository {    private EFDbContext context = new EFDbContext();    public IQueryable<Book> Books {        get { return context.Books; }    }}

在我們的這個倉儲類中,我們改使用EF,通過建立一個EFDbContext類的執行個體來擷取資料庫中的資料。如你所見,我們不需要自己寫ADO.NET代碼去串連和讀取資料庫,非常簡潔明了,我們就是這樣使用Entity Framework的。我們來看一下運行效果吧:

到這我們已經成功使用EF串連上了資料庫,並從資料庫中讀取出來了資料。我們還可以通過Linq進行非常靈活的查詢,就像寫SQL一樣。比如要查詢價格在100元以下的前10條記錄,並且按價格從低到高顯示,那麼我們可以在BookShop.WebUI工程下的BookController中的List方法中這樣寫:

public ViewResult List() {    return View(repository.Books        .OrderBy(b => b.Price)        .Where(b => b.Price < 100)        .Take(10));}

或許你很快就會對EF擷取資料庫的方式產生這樣的疑問:EF從資料庫中讀取整個Books表的資料到記憶體,然後返回給調用者(上面代碼中的repository.Books)用Linq語句過濾使用者想要的前10條資料,如果Books表中有幾百萬條資料,那記憶體豈不是完蛋了,EF不會這麼傻吧?EF會不會根據Linq查詢語句智能地產生SQL文本再到資料庫中去查詢資料呢?這裡就要講講IQueryable和IEnumerable了。

IQueryable 和 IEnumerable

其實,對於上面的即有過慮又有排序的條件查詢Linq語句,EF是讀取資料庫中整個Books表中的資料到記憶體,還是根據Linq查詢語句智能的產生SQL再執行查詢,完全編碼者來決定的。我們開啟BookShop.Domain工程的BookRepository類檔案,請注意該類中Books屬性的傳回型別:

...public IQueryable<Book> Books {    get { return context.Books; }}

我們對使用IQueryable作為傳回型別提了個疑問:為什麼用IQueryable而不用IEnumerable作為傳回型別?答案是:使用IQueryable,EF會根據調用者的Linq運算式先產生相應的SQL查詢語句,然後到資料庫中執行查詢,查詢出來的資料即是使用者想要的資料;而使用IEnumerable,Linq運算式的過濾、排序等操作都是在記憶體中發生的,即EF會先從資料庫中把整個表的資料查詢出來放在記憶體中,然後由調用者使用Linq語句進行過濾、排序等操作。是不是這樣呢?我們來監視一下兩種情況EF產生的SQL語句就知道了。

我們先來看看使用IQueryable的情況。重新運行一下程式,然後使用SQL Server Management Studio的活動和監視器查看一下我們的BookShop應用程式所執行的SQL語句,結果如下:

結果證明使用IQueryable,EF是先根據Linq運算式產生相應的SQL語句再執行查詢的。

我們再稍稍修改一下代碼來看看用IEnumerable的情況。把BookRepository類修改如下:

public class BookRepository : IBookRepository {    private EFDbContext context = new EFDbContext();    public IEnumerable<Book> Books {        get { return context.Books; }    }}

當然BookRepository類所實現的IBookRepository介面(在BookShop.Domain工程的Abstract檔案夾中)也要改一下:

public interface IBookRepository {    IEnumerable<Book> Books { get; }}

再重新運行一下應用程式,用活動和監視器查看最後執行的SQL語句如:

我們看到改用IEnumerable後,EF產生的SQL沒有任何過濾、排序等的操作,它一次把表中的所有資料都Select出來,和上面寫的Linq運算式一點都沒關係。

IQueryable雖然可以很智能地根據Linq運算式產生相應的SQL語句,但畢竟有一個分析Linq運算式的過程,相對來說效能比IEnumerable要差。那麼我們什麼時候用IEnumerable,什麼時候用IQueryable呢?我想,對於少量的資料(比如從資料庫中讀取應用程式相關的系統資訊)和不需要對資料進行過濾操作的情況,用IEnumerable比較適合;對於資料量較大需要對資料進行過濾(比如分頁查詢)的情況,則用IQueryable比較合適。

以上就是[ASP.NET MVC 小牛之路]06 - 使用 Entity Framework的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.