第 4 部分:模型和資料存取
作者 :JonGaloway
MVC 音樂市集是一個教學課程應用程式,會介紹並說明如何使用 ASP.NET MVC 和 Visual Studio 進行 Web 開發。
MVC Music Store 是輕量型範例商店實作,可線上銷售音樂相簿,並實作基本網站管理、使用者登入和購物車功能。
本教學課程系列詳細說明建置 ASP.NET MVC 音樂市集範例應用程式所採取的所有步驟。 第 4 部分涵蓋模型和資料存取。
到目前為止,我們剛剛將「虛擬資料」從控制器傳遞至檢視範本。 現在我們已準備好連結實際資料庫。 在本教學課程中,我們將說明如何使用 SQL Server Compact Edition (通常稱為 SQL CE) 作為資料庫引擎。 SQL CE 是免費、內嵌的檔案式資料庫,不需要任何安裝或設定,這讓本機開發變得非常方便。
使用 Entity Framework Code-First 進行資料庫存取
我們將使用包含在 ASP.NET MVC 3 專案中的 Entity Framework (EF) 支援來查詢和更新資料庫。 EF 是彈性的物件關聯式對應 (ORM) 資料 API,可讓開發人員以物件導向的方式查詢和更新儲存在資料庫中的資料。
Entity Framework 第 4 版支援稱為程式碼優先的開發範例。 程式碼優先可讓您藉由撰寫簡單的類別 (也稱為 POCO,從「plain-old」 CLR 物件) 來建立模型物件,甚至可以從您的類別即時建立資料庫。
模型類別的變更
在本教學課程中,我們將利用 Entity Framework 中的資料庫建立功能。 不過,在這麼做之前,讓我們先對模型類別進行一些微幅變更,以新增稍後將使用的某些專案。
新增作者模型類別
我們的相簿將會與「藝術師」相關聯,因此我們會新增簡單的模型類別來描述「藝術師」。 使用如下所示的程式碼,將新的類別新增至名為 Artist.cs 的 Models 資料夾。
namespace MvcMusicStore.Models
{
public class Artist
{
public int ArtistId { get; set; }
public string Name { get; set; }
}
}
更新模型類別
更新 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; }
public Artist Artist { get; set; }
}
}
接下來,對內容類型類別進行下列更新。
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; }
}
}
新增App_Data資料夾
我們會將App_Data目錄新增至專案,以保存SQL Server Express資料庫檔案。 App_Data 是 ASP.NET 中的特殊目錄,其具有正確的資料庫存取權安全性存取權限。 從 [專案] 功能表中,選取 [新增 ASP.NET 資料夾],然後App_Data。
在 web.config 檔案中建立連接字串
我們會將幾行新增至網站的組態檔,讓 Entity Framework 知道如何連線到我們的資料庫。 按兩下位於專案根目錄中的Web.config檔案。
捲動至此檔案底部,並直接在最後一 < 行上方新增 connectionStrings > 區段,如下所示。
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="Data Source=|DataDirectory|MvcMusicStore.sdf"
providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>
</configuration>
新增內容類別別
以滑鼠右鍵按一下 Models 資料夾,然後新增名為 MusicStoreEntities.cs 的新類別。
此類別將代表 Entity Framework 資料庫內容,並會為您處理我們的建立、讀取、更新和刪除作業。 此類別的程式碼如下所示。
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 類別就能夠處理我們的資料庫作業。 既然我們已連結,讓我們再將一些屬性新增至模型類別,以利用資料庫中的一些額外資訊。
新增我們的市集目錄資料
我們將利用 Entity Framework 中的功能,將「種子」資料新增至新建立的資料庫。 這會預先填入我們的市集目錄,其中包含內容類型、藝術師和相簿的清單。 MvcMusicStore-Assets.zip下載 - 其中包含我們稍早在本教學課程中使用的網站設計檔案 - 具有此種子資料的類別檔案,位於名為 Code 的資料夾中。
在 Code / Models 資料夾中,找出 SampleData.cs 檔案,並將其放入專案中的 Models 資料夾中,如下所示。
現在我們需要新增一行程式碼,以告知 Entity Framework 該 SampleData 類別。 按兩下專案根目錄中的 Global.asax 檔案以開啟它,並將下列這一行新增至Application_Start方法頂端。
protected void Application_Start()
{
System.Data.Entity.Database.SetInitializer(
new MvcMusicStore.Models.SampleData());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
此時,我們已完成為專案設定 Entity Framework 所需的工作。
查詢資料庫
現在讓我們更新 StoreController,而不是使用「虛擬資料」,而是改為呼叫資料庫來查詢其所有資訊。 我們將從宣告 StoreController 上的欄位開始,以保存名為 storeDB 的 MusicStoreEntities 類別實例:
public class StoreController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities();
更新存放區索引以查詢資料庫
MusicStoreEntities 類別是由 Entity Framework 維護,並公開資料庫中每個資料表的集合屬性。 讓我們更新 StoreController 的索引動作,以擷取資料庫中的所有內容類型。 我們先前透過硬式編碼字串資料來執行此作業。 現在我們可以改用 Entity Framework 內容 Generes 集合:
public ActionResult Index()
{
var genres = storeDB.Genres.ToList();
return View(genres);
}
檢視範本不需要進行任何變更,因為我們仍然傳回之前傳回的相同 StoreIndexViewModel - 我們現在剛從資料庫傳回即時資料。
當我們再次執行專案並流覽 「/Store」 URL 時,我們現在會看到資料庫中所有內容類型的清單:
更新市集流覽和詳細資料以使用即時資料
使用 /Store/Browse?genre=[some-genre] 動作方法,我們會依名稱搜尋內容類型。 我們只預期一個結果,因為我們不應該有兩個專案用於相同的內容類型名稱,因此我們可以使用 。LINQ 中的 Single () 延伸模組可查詢適當的 Genre 物件,例如此 (尚未輸入此物件) :
var example = storeDB.Genres.Single(g => g.Name == "Disco");
Single 方法會採用 Lambda 運算式做為參數,指定我們想要單一的 Genre 物件,使其名稱符合我們定義的值。 在上述案例中,我們會載入具有符合 Disco 之 Name 值的單一 Genre 物件。
我們將利用 Entity Framework 功能,讓我們在擷取內容類型物件時,也指出我們想要載入的其他相關實體。 這項功能稱為「查詢結果成形」,可讓我們減少存取資料庫所需的次數,以擷取我們需要的所有資訊。 我們想要預先擷取我們擷取的「內容類型」的相簿,因此我們會更新查詢,以包含來自 Genres.Include (「相簿」) ,以指出我們也想要相關的相簿。 這會更有效率,因為它會在單一資料庫要求中擷取我們的內容類型和相簿資料。
有了說明,以下是更新的流覽控制器動作外觀:
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);
}
我們現在可以更新市集流覽檢視,以顯示每個內容類型中可用的相簿。 開啟在 /Views/Store/Browse.cshtml) 中找到的檢視 (範本,然後新增相簿的專案符號清單,如下所示。
@model MvcMusicStore.Models.Genre
@{
ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>
<ul>
@foreach (var album in Model.Albums)
{
<li>
@album.Title
</li>
}
</ul>
執行我們的應用程式並流覽至 /Store/Browse?genre=,顯示我們的結果現在已從資料庫提取,並在選取的內容類型中顯示所有相簿。
我們將對 /Store/Details/[id] URL 進行相同的變更,並將虛擬資料取代為資料庫查詢,以載入識別碼符合參數值的相簿。
public ActionResult Details(int id)
{
var album = storeDB.Albums.Find(id);
return View(album);
}
執行我們的應用程式並流覽至 /Store/Details/1,會顯示我們的結果現在已從資料庫提取。
現在,我們的 [市集詳細資料] 頁面已設定為依 [相簿識別碼] 顯示相簿,讓我們更新 [ 流覽 ] 檢視以連結至 [詳細資料] 檢視。 我們將使用 Html.ActionLink,就像我們在上一節結束時從市集索引連結至市集流覽所做的一樣。 [流覽] 檢視的完整來源會出現在下方。
@model MvcMusicStore.Models.Genre
@{
ViewBag.Title = "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>
我們現在能夠從 [市集] 頁面流覽至 [內容類型] 頁面,其中列出可用的相簿,然後按一下相簿,即可檢視該相簿的詳細資料。