第 4 部:モデルとデータ アクセス

作成者: Jon Galloway

MVC ミュージック ストアは、WEB 開発に MVC と Visual Studio ASP.NET 使用する方法を段階的に紹介し、説明するチュートリアル アプリケーションです。

MVC ミュージック ストアは、オンラインで音楽アルバムを販売し、基本的なサイト管理、ユーザー サインイン、ショッピング カート機能を実装する軽量のサンプル ストア実装です。

このチュートリアル シリーズでは、ASP.NET MVC Music Store サンプル アプリケーションをビルドするために実行されるすべての手順について詳しく説明します。 パート 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 では、code-first と呼ばれる開発パラダイムがサポートされています。 コードファーストを使用すると、単純なクラス ("プレーン古い" CLR オブジェクトから POCO とも呼ばれます) を記述してモデル オブジェクトを作成できます。また、クラスからすぐにデータベースを作成することもできます。

モデル クラスの変更

このチュートリアルでは、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; }
    }
}

次に、次に、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; }
    }
}

App_Data フォルダーの追加

SQL Server Express データベース ファイルを保持するために、プロジェクトに App_Data ディレクトリを追加します。 App_Dataは、データベース アクセスに対する適切なセキュリティ アクセス許可を既に持っている ASP.NET の特殊なディレクトリです。 [プロジェクト] メニューの [ASP.NET フォルダーの追加] を選択し、App_Dataします。

A S P を追加する [プロジェクト] メニューのスクリーンショット。N E T フォルダーを使用してアプリ データを選択します。

web.config ファイルでの接続文字列の作成

Entity Framework がデータベースへの接続方法を認識できるように、Web サイトの構成ファイルに数行を追加します。 プロジェクトのルートにある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 という名前のフォルダーに、このシード データを含むクラス ファイルがあります。

[コード/ モデル] フォルダー内で SampleData.cs ファイルを見つけて、次に示すように、プロジェクトの Models フォルダーにドロップします。

サンプル データ C S ファイルを見つけてストア カタログ データを追加する Code または Models フォルダーのスクリーンショット。

ここで、その SampleData クラスについて Entity Framework に伝えるために、1 行のコードを追加する必要があります。 プロジェクトのルートにある 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 の Index アクションを更新して、データベース内のすべてのジャンルを取得してみましょう。 以前は、文字列データをハードコーディングすることでこれを行っていました。 これで、代わりに Entity Framework コンテキスト Generes コレクションを使用できます。

public ActionResult Index()
{
    var genres = storeDB.Genres.ToList();
    return View(genres);
 }

以前に返したのと同じ StoreIndexViewModel をまだ返しているので、ビュー テンプレートに変更を加える必要はありません。現在はデータベースからライブ データを返しています。

プロジェクトをもう一度実行し、"/Store" URL にアクセスすると、データベース内のすべてのジャンルの一覧が表示されます。

データベース内のすべてのジャンルの一覧のスクリーンショット。

ライブ データを使用するようにストアの参照と詳細を更新する

/Store/Browse?genre=[some-genre] アクション メソッドを使用して、名前でジャンルを検索しています。 同じジャンル名に対して 2 つのエントリを持つ必要がないため、結果は 1 つだけです。そのため、 を使用できます。LINQ の Single() 拡張機能で、次のような適切な Genre オブジェクトを照会します (まだ入力しないでください)。

var example = storeDB.Genres.Single(g => g.Name == "Disco");

Single メソッドは、ラムダ式をパラメーターとして受け取ります。このメソッドは、定義した値と名前が一致するように 1 つの Genre オブジェクトが必要であることを指定します。 上記の場合は、Disco に一致する Name 値を持つ 1 つの Genre オブジェクトを読み込んでいます。

Entity Framework 機能を利用して、Genre オブジェクトが取得されたときに読み込む他の関連エンティティを示すことができます。 この機能はクエリ結果の整形と呼ばれ、必要なすべての情報を取得するためにデータベースにアクセスする必要がある回数を減らすことができます。 取得するジャンルのアルバムを事前にフェッチする必要があるため、Genres.Include("Albums") から含めるようにクエリを更新して、関連するアルバムも必要であることを示します。 これは、1 つのデータベース要求でジャンルとアルバムの両方のデータを取得するため、より効率的です。

説明が間に合わないので、更新された [コントローラーの参照] アクションの外観を次に示します。

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=Jazz を参照すると、結果がデータベースから取得され、選択したジャンルのすべてのアルバムが表示されます。

データベースからプルされたときの結果のスクリーンショットには、選択したジャンルのすべてのアルバムが表示されます。

/Store/Details/[id] URL に同じ変更を加え、ダミー データを、パラメーター値と一致するアルバムを読み込むデータベース クエリに置き換えます。

public ActionResult Details(int id)
{
    var album = storeDB.Albums.Find(id);
 
    return View(album);
}

アプリケーションを実行し、/Store/Details/1 を参照すると、結果がデータベースから引き出されていることが示されます。

[ストアの詳細] ページのスクリーンショットは、結果もデータベースからプルされていることを示しています。

[ストアの詳細] ページがアルバム ID でアルバムを表示するように設定されたので、[ 参照 ] ビューを更新して [詳細] ビューにリンクします。 前のセクションの最後にあるストア インデックスからストア 参照へのリンクとまったく同じように、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>

ストア ページから利用可能なアルバムを一覧表示する [ジャンル] ページに移動できるようになりました。アルバムをクリックすると、そのアルバムの詳細を表示できます。

[ストア] ページから [ジャンル] ページに移動できるスクリーンショット。