第 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。

[專案] 功能表的螢幕擷取畫面,以新增 A S P 。N E T 資料夾以選取應用程式資料。

在 web.config 檔案中建立連接字串

我們會將幾行新增至網站的組態檔,讓 Entity Framework 知道如何連線到我們的資料庫。 按兩下位於專案根目錄中的Web.config檔案。

方案總管中 Web 組態檔的螢幕擷取畫面,以在其中建立連接字串。

捲動至此檔案底部,並直接在最後一 < 行上方新增 connectionStrings > 區段,如下所示。

<connectionStrings>
    <add name="MusicStoreEntities"
     connectionString="Data Source=|DataDirectory|MvcMusicStore.sdf"
     providerName="System.Data.SqlServerCe.4.0"/>
  </connectionStrings>  
</configuration>

新增內容類別別

以滑鼠右鍵按一下 Models 資料夾,然後新增名為 MusicStoreEntities.cs 的新類別。

新增內容類別別之 Models 資料夾的螢幕擷取畫面。

此類別將代表 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 資料夾中,如下所示。

[程式碼] 或 [模型] 資料夾的螢幕擷取畫面,以找出範例資料 C S 檔案,並新增存放區目錄資料。

現在我們需要新增一行程式碼,以告知 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>

我們現在能夠從 [市集] 頁面流覽至 [內容類型] 頁面,其中列出可用的相簿,然後按一下相簿,即可檢視該相簿的詳細資料。

能夠從 [市集] 頁面流覽至 [內容類型] 頁面的螢幕擷取畫面。