4.1 使用Entity Framework code-first連接數據庫
在本教程中,我們使用.NET 4中的Entity Framework(EF)來訪問數據庫以及對數據庫中的數據進行增刪查改操作。EF是一個非常靈活的對象關係映射(ORM:object relational mapping)數據庫API,它使得開發者可以用一種面向對象的方式在數據庫中進行增刪查改操作。
Entity Framework 4支持一種被稱爲code-first的開發範例。code-first允許你用書寫簡單類的方式來創建模型對象(也稱POCO對象),甚至可以直接通過模型類來創建數據庫。爲了要使用code-first,首先需要安裝EFCodeFirst類庫。
4.2 使用NuGet來安裝EFCodeFirst
這裏我們打算使用NuGet包管理器(安裝ASP.NET MVC3時會同時自動被安裝)來在本應用程序中添加EFCodeFirst類庫。
點擊“工具”菜單下的“Library Package Manager”子菜單下的“Add Library Package Reference”菜單選項,如圖4-1所示。
圖4-1 使用NuGet包管理器
點擊“Add Library Package Reference”菜單選項後,將會彈出一個對話框,標題爲“Add Library Package Reference”,如圖4-2所示。
圖4-2 “Add Library Package Reference”對話框
默認狀態下,左邊的“All”選項處於選擇狀態。因爲還沒有安裝任何包,所以右邊面板中顯示“找不到任何項”,如圖4-3所示。
圖4-3 默認狀態下顯示“找不到任何項”
點擊左邊面板中的“online”選項,NuGet包管理器將會在服務器上檢索所有當前能夠獲取的包,如圖4-4所示。
圖4-4 NuGet包管理器正在檢索包信息
服務器上有幾百個當前能夠獲取的包,現在我們只關注EFCodeFirst包。在右上角的搜索輸入框中輸入“EFCode”。在檢索結果中,選擇EFCodeFirst包,並且點擊Install按鈕安裝包,如圖4-5所示。
圖4-5 選擇EFCodeFirst包並安裝
點擊了install按鈕後,會彈出一個接受許可證窗口,如圖4-6所示,在這個窗口中必須要點擊“I Accept”按鈕,接受許可證條款,安裝才能繼續進行。
圖4-6 接受許可證窗口
安裝完畢後,點擊close按鈕。我們的MvcBookStore工程中會自動加載EntityFramework程序集,其中包含了EFCodeFirst類庫,如圖4-7所示。
圖4-7 安裝完畢後EntityFramework程序集被自動加載
4.3 在web.config文件中創建一個連接字符串
接下來我們將在應用程序的設置文件中追加一個連接字符串,供Entity Framework連接數據庫時所用。鼠標雙擊解決方案資源管理器中工程根目錄下的Web.config文件,如圖4-8所示。
圖4-8 解決方案資源管理器中工程根目錄下的Web.config文件
在該文件的底部追加一個<connectionStrings>區段,代碼如下所示。
<configuration>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true"
providerName="System.Data.SqlClient" />
<add name="BookStoreEntities"
connectionString=" Data Source=.\SQLEXPRESS;
Initial Catalog=BookStore;Persist Security Info=True;
User ID=aaa;Password=aaaaaaa "
providerName="System.Data.SqlClient" />
</connectionStrings>
4.4 追加一個上下文類
鼠標右擊Models文件夾,追加一個新類,名字爲BookStoreEntities.cs,如圖4-9所示。
圖4-9 追加BookStoreEntities.cs上下文類
這個類代表了Entity Framework數據庫上下文,爲我們處理數據的增刪查改操作,追加該類中代碼如下所示。
using System.Data.Entity;
namespace MvcBookStore.Models
{
public class BookStoreEntities : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Genre> Genres { get; set; }
}
}
這樣就足夠了,不需其他任何設置,譬如專有接口等等。通過對DbContext基礎類的擴展,我們的BookStoreEntities類可以替我們實現有關數據庫的操作。接下來,讓我們在我們的模型類中追加一些屬性,以便獲取數據庫中的一些附加信息。
4.5 修改我們的模型類
將Book類中的代碼修改爲如下所示的代碼。
namespace MvcBookStore.Models
{
public class Book
{
public int Id { get; set; }
public int GenreId { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public Genre Genre { get; set; }
}
}
接下來,讓我們修改Genre類中的代碼如下所示。
using System.Collections.Generic;
namespace MvcBookStore.Models
{
public partial class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Book> Books { get; set; }
}
}
4.6 查詢數據庫
接下來,讓我們更新我們的StoreController控制器類,使其可以到我們的數據庫中進行數據的查詢。首先,我們創建一個MusicStoreEntities類的實例,並將其命名爲storeDB。
public class StoreController : Controller
{
BookStoreEntities storeDB = new BookStoreEntities();
4.7 在Index方法中使用LINQ查詢
Entity Framework維護BookStoreEntities類,並且爲數據庫中每張數據表向外公佈一個集合屬性。我們可以使用.NET中的LINQ查詢功能來針對這些屬性書寫強類型的查詢表達式,這些查詢表達式將執行數據庫中的查詢並且返回一些易於我們編程時使用的對象。
修改StoreController控制器類中Index這個action方法,使其可以到數據表中查詢所有的書籍種類名稱。這裏我們使用如下代碼中所示的LINQ查詢來獲取數據表中所有種類(Genre)的Name(名稱)屬性。
public ActionResult Index()
{
var genres = storeDB.Genres.ToList();
return View(genres);
}
接下來需要修改Views文件夾下的Store文件夾中的Index.cshtml文件夾中的一處地方,將“genre.ID”修改爲“GenreId”,代碼如下所示。
<li>@Html.ActionLink(genre.Name,"Browse", new {id=genre.GenreId})</li>
我們不需要對之前我們的視圖模板中的代碼做出任何修改,該視圖模板可以直接顯示從數據表中取出的書籍種類信息。
重新運行應用程序,並訪問“/Store”這個URL地址,該頁面中目前沒有任何書籍種類信息被顯示,如圖4-10所示。
圖4-10 數據表中尚未添加種類信息時的頁面顯示
打開你在web.config中指定連接的SQL Server Express的SQL Management Studio,該服務器中已被追加了一個BookStore數據庫,該數據庫中被自動追加了一張Book數據表與一張Genre數據表,打開Genre數據表,輸入如表4-1中所示的數據。
表4-1 在Genre表中追加的數據
GenreId(自增長ID) |
Name(種類名稱) |
Description(描述) |
1 |
小說 |
包括玄幻、穿越、青春校園、魔幻、都市、歷史、科幻、商戰、軍事等等 |
2 |
文學 |
包括古典文學、現代文學、詩歌、散文等等 |
3 |
社會科學 |
包括勵志、兩性關係、管理、股票、軍事、政治、歷史、法律、哲學、宗教等等 |
4 |
藝術 |
包括繪畫、書法、影視、動畫、戲曲、攝影、雕塑、音樂、舞蹈等等 |
5 |
教材 |
包括小學課外參考書、初中課外參考書、高中課外參考書等等 |
6 |
生活 |
包括養生、傢俱、裝修、旅遊、育兒、飲食等等 |
7 |
科學 |
包括計算機類、機械類、建築類、醫學類、交通類、電子類等等 |
重新運行應用程序,並訪問“/Store”這個URL地址,該頁面中顯示所有書籍種類信息,如圖4-11所示。
圖4-11 頁面中顯示所有書籍種類信息
4.8 在Browse方法與Details方法中使用LINQ查詢
通過輸入“/Store/Browse/[ID]”這個URL地址,我們應該可以通過一個ID來查找一種書籍種類。我們只想要一條查詢結果,因爲書店中不可能有兩個相同的書籍種類,所以我們採用如下所示的方法來查詢Genre對象。
var example = storeDB.Genres.Single(g => g.GenreId == 1);
此處我們將利用Entity Framework中的一個特性,該特性允許我們獲取Genre對象時同時可以獲取與之相關聯的其他實體信息,該特性被稱爲Query Result Shaping,它可以減少當我們獲取所有需要使用到的數據對象信息時訪問數據庫的次數。我們可以爲種類預裝載書籍信息,所以修改查詢表達式,使用Genres.Include(“Books”)來標示我們同時還需要獲取相關聯的書籍信息。這種做法是十分高效的,因爲它在一次數據庫請求中同時獲取了種類信息和與之相關聯的書籍信息。
Browse方法中最終被修改代碼如下所示。
public ActionResult Browse(int id)
{
//從數據庫中獲取書籍種類信息和與之相關聯的書籍信息
var genreModel = storeDB.Genres.Include("Books").Single(g => g.GenreId ==
id);
return View(genreModel);
}
現在我們修改書籍種類信息展示頁面,展示每一個書籍種類中的所有書籍。打開該視圖模板(Views文件夾下的Store文件夾中的Browse.cshtml文件),修改代碼如下所示。
@model MvcBookStore.Models.Genre
@{
ViewBag.Title = "挑選書籍";
}
<h2>書籍種類: @Model.Name</h2>
<ul>
@foreach (var book in Model.Books)
{
<li>
@book.Title
</li>
}
</ul>
重新運行應用程序,並訪問“/Store/Browse/1”這個URL地址,該頁面中目前沒有任何書籍信息被顯示,如圖4-12所示。
圖4-12數據表中尚未添加書籍信息時的頁面顯示
打開你在web.config中指定連接的SQL Server Express的SQL Management Studio,打開Book數據表,輸入如表4-2中所示的數據。
表4-2 在Book表中追加的數據
Id(自增長字段) |
GenreId |
AuthorId |
Title |
Price |
1 |
1 |
1 |
1988:我想和這個世界談談 |
25 |
2 |
1 |
2 |
風中的費洛蒙 |
28 |
3 |
1 |
3 |
海邊的卡夫卡 |
27 |
4 |
1 |
4 |
大方 |
25 |
5 |
1 |
5 |
騎誓•蠱騎士的靈印 |
20 |
6 |
1 |
1 |
獨唱團 |
16 |
7 |
1 |
6 |
蘇小姐的婚事:六六的十二則"婚事"啓示錄 |
25 |
8 |
1 |
7 |
不能承受的生命之輕 |
29 |
9 |
1 |
8 |
追風箏的人 |
25 |
10 |
1 |
9 |
聖經密碼 |
28 |
圖4-13 頁面中顯示所有小說類的書籍信息
接下來我們修改Details這個action方法中的代碼,當用戶輸入“/Store/Details/[ID]”這個URL地址時,能夠到數據庫中查詢書籍信息,並顯示在頁面上。代碼如下所示。
public ActionResult Details(int id)
{
var book = storeDB.Books.Find(id);
return View(book);
}
重新運行應用程序,並訪問“/Store/Details/1”這個URL地址,頁面中顯示出了對應的書籍信息,如圖4-14所示。
圖4-14 頁面中顯示單本小說信息
最後,讓我們修改書籍種類信息展示頁面,使其能夠鏈接到單本小說信息展示頁面。我們使用Html.ActionLink方法,使用方法類似於前文所述的從書籍種類列表頁面與書籍種類信息展示頁面之間的鏈接,代碼如下所示。
@model MvcBookStore.Models.Genre
@{
ViewBag.Title = "挑選書籍";
}
<h2>書籍種類: @Model.Name</h2>
<ul>
@foreach (var book in Model.Books)
{
<li>
@Html.ActionLink(book.Title,"Details",new { id = book.Id })
</li>
}
</ul>
現在,當我們點擊書籍種類信息裏的某本小說時,頁面就能跳轉到單本小說信息展示頁面並顯示該書籍的信息了。