轉自http://firechun.blog.163.com/blog/static/318045222011029105328664/
迄今為止,我們只是把“類比資料”從控制器傳遞到視圖模板,現在,我們要掛上真實的資料庫了。在教程中,我們示範了如何使用免費的SQL Server Express做為我們的資料庫引擎,這些代碼也同樣適用於完整版的SQL Server。
首先在項目中添加App_Data目錄存放SQL Server Express資料庫檔案。App_Data是ASP.NET的特定目錄,它已經為資料庫訪問設定了合適的存取權限。
添加資料庫
按右鍵項目,選擇“添加->添加ASP.NET檔案夾->App_Data”
現在可以添加資料庫檔案了。為教程使用的資料庫MvcMusicStore.mdf已經建立好了,它包含在可供下載的項目包的MvcMusicStore-Assets/Data目錄下,:http://mvcmusicstore.codeplex.com
注 意: MvcMusicStore-Assets/Data 目錄中還包括一個 T-SQL 指令碼 (MvcMusicStore-Create.sql) 可以在一個SQL Server執行個體中建立 MvcMusicStore 資料庫,假如你不能使用SQL Server Express的話。
(以下是如何添加現有項到項目中的說明和,此處略過,只需要將下載的MvcMusicStore.mdf做為現有項添加到App_Data目錄下就行了)
看看資料庫的關係圖:
你可以看到描述音樂的Album、Genre和Artist類,還有涉及到倉庫管理的Cart(購物車)、Order(訂單)以及OrderDetails(訂單明細)
使用Entity Framework串連資料庫
資料庫已經添加到項目中,我們可以編寫代碼查詢和更新資料庫,這裡我們使用.NET 4中的Entity Framework(EF)來實現。EF是一個靈活的對象關係映射(ORM)資料API,允許開發人員使用物件導向的方式查詢和更新資料庫中的資料。
EF4支援的開發模式稱為代碼優先。代碼優先允許你編寫簡單的類建立模型對象,甚至允許你從類中動態建立資料庫,要使用代碼優先,你必須安裝EFCodeFirst 庫。
注意: 代碼優先可以從你的模型類中建立資料庫。在本教程中,我們使用現有的資料庫,其中積極式載入了由完整的類別和藝術家資訊組成的音樂專輯,要獲得從模型產生資料的樣本,參看Scott Hanselman’s 介紹的 ASP.NET MVC 教程: http://www.asp.net/mvc/tutorials/getting-started-with-mvc-part1.
用NuGet安裝EFCodeFirst庫
在這一節,我們將使用NuGet Package Manager(由ASP.NET MVC 3自動安裝)把EFCodeFirst添加到MvcMusicStore項目中,NuGet Package Manager隨ASP.NET MVC 3一起安裝。
(沒有安裝MVC 3,當然也就沒NuGet Package Manager,下面插入一段如何安裝NuGet Package Manager的過程)
在VS2010中選擇“工具->擴充管理器”
在“擴充管理器”對話方塊中選擇“聯機庫”
搜尋完成後,找到NuGet Package Manager,下載安裝並重啟VS2010,下面的步驟和原文一樣了。
從工具菜單中,選擇 Library Package Manager\Add Library Package Reference(如果出錯,重啟VS2010,重新再來)
Add Library Package Reference對話方塊顯示
選擇online
這裡會有幾百個包,我們只對EFCodeFirst感興趣,在搜尋方塊中輸入“EFCode”,選擇“EFCode”包並點擊安裝。
包安裝完成之後,點擊“Close”按紐。安裝程式已經下載EFCodeFirst庫並把它添加到MvcMusicStore項目中,EFCodeFirst庫在EntityFrameword.dll檔案中。
在Web.config檔案中建立連接字串
在網站的Web.config添加一行以便讓Entity Framework知道如何連接字串,在項目根目錄中找到並雙擊Web.config檔案:
滾動到檔案底部,添加<connectionStrings>節,如下所示:
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="data source=.\SQLEXPRESS;
Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|\MvcMusicStore.mdf;
User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
添加Context類
在Models檔案夾上單擊右鍵添加一個新類:MusicStoreEntities.cs
這個類用來呈現Entity Framework上下文(Context),為我們處理建立、讀取、更新和刪除操作,代碼如下所示:
using System.Data.Entity;
namespace MvcMusicStore.Models
{
public class MusicStoreEntities : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
}
}
就這樣,不需要其它配置、特殊的介面等等。派生自DbContext的MusicStoreEntities類為我們各種處理資料庫操作。瞭解了如何和資料庫掛接,我們再給模型類增加一些屬性以便應用程式資料庫中追加的資訊。
更新模型類
更新Album類,如下:
namespace MvcMusicStore.Models
{
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public int ArtistId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string AlbumArtUrl { get; set; }
public Genre Genre { get; set; }
}
}
下面接著更新Genre類
using System.Collections.Generic;
namespace MvcMusicStore.Models
{
public partial class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Album> Albums { get; set; }
}
}
查詢資料庫
現在可以更新StoreController了,用從資料庫中查詢到的資訊替換“類比資料”。首先在StoreController類中聲明一個欄位用來儲存MusicStoreEntities的執行個體:
public class StoreController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities();
在Store的Index方法中使用LINQ查詢運算式
MusicStoreEntities類由Entity Framework維護,並公開了資料庫中每個表的屬性集合。我們可以使用.NET中很酷的LINQ(Language-integrated Query (LINQ))針對這些集合編寫強型別查詢運算式,它可以對資料庫執行這些代碼並返回對象,並且編程更加容易。
現在把之前在StoreController中Index動作方法中寫入程式碼產生的字串資料(類別名稱)更新為從資料庫中檢索,我們編寫一個如下所示的LINK查詢運算式從資料庫中檢索每個類別的Name屬性。
public ActionResult Index()
{
var genres = storeDb.Genres.ToList();
return View(genres);
}
對之前的Index.aspx視圖不需要做任何改變,只不過我們現在得到的是資料庫中的資料。
運行項目並訪問/Store URL,我們看到了資料庫中的所有類別。
在Store的Broswe、Details和Index方法中使用LINQ擴充方法
在指向 /Store/Browse?genre=[some-genre] 的動作方法中,我們按名稱查詢類別,因為不可能有兩個相同名稱的類別,我們只有一個返回結果,所以可以使用LINQ查詢的.Single()方法來返回Genre對象。如:
var example = storeDB.Genres.Single(g => g.Name == “Disco”);
Single方法的參數是一個Lambda運算式,用它來確定和我們定義的名稱相符的單個Genre對象。上面的例子中,我們讀取了一個名稱為“Disco”的Genre對象。
檢 索到Genre對象時,我們可以利用Entity Framework的特點來標示出該對象的相關實體,這種Entity Framework的特點被稱為Query Result Shaping(查詢結果整形?沒有找到正式的中文叫法),這可以在我們從資料庫檢索我們所需要的資訊時降低訪問資料庫的次數。我們想為檢索到的類別預先 擷取相關的唱片,因此更新我們的查詢,讓它包括Genres.Include("Albums"),以表明我們希望獲得相關的唱片。因為在單次的資料庫請 求中同時查詢唱片和類別,效能會更好。
更新Browse方法如下:
public ActionResult Browse(string genre)
{
// Retrieve Genre and its Associated Albums from database
var genreModel = storeDB.Genres.Include("Albums")
.Single(g => g.Name == genre);
return View(genreModel);
}
更新Storer的Browse視圖以顯示每個類別下的唱片,開啟視圖模板( /Views/Store/Browse.aspx)添加唱片列表代碼:
<h2>
Browsing Genre:<%:Model.Name %></h2>
<ul>
<% foreach (var album in Model.Albums)
{ %>
<li><%:album.Title%></li>
<% } %>
</ul>
運行程式並瀏覽/Store/Browse?genre=Jazz顯示我們從資料庫獲得的資料,將會顯示我們指定類別下的所有唱片。
對/Store/Details/[id] URL做相同的修改,使用從資料庫中查詢到的和Id值相符的資料來替換“類比資料”。
public ActionResult Details(int id)
{
var album = storeDB.Albums.Find(id);
return View(album);
}
運行應用程式,瀏覽/Store/Details/5,顯示我們從資料庫中獲得的結果。
現在Store Details頁面被設定為按Id顯示唱片,更新Browse視圖,讓它連結到Details視圖。我們使用Html.ActionLink()方法,但並不完全象之前從Store Index連結到Store Browse那樣,完整代碼如下:
<h2>
Browsing Genre:<%:Model.Name %></h2>
<ul>
<% foreach (var album in Model.Albums)
{ %>
<li><%:Html.ActionLink(album.Title, "Details", new { id = album.AlbumId }) %></li>
<% } %>
</ul>
現在我們可以Store頁面瀏覽到Genre頁面,可以列出所在唱片,並且點擊唱片時可以查看唱片的詳細資料。