LINQ to SQL でモデル クラスを作成する (C#)
提供元: Microsoft
このチュートリアルの目的は、ASP.NET MVC アプリケーションのモデル クラスを作成する方法の 1 つについて説明することです。 このチュートリアルでは、Microsoft LINQ to SQL を利用してモデル クラスをビルドし、データベース アクセスを実行する方法について説明します。
このチュートリアルの目的は、ASP.NET MVC アプリケーションのモデル クラスを作成する方法の 1 つについて説明することです。 このチュートリアルでは、Microsoft LINQ to SQL を利用してモデル クラスをビルドし、データベース アクセスを実行する方法について説明します
このチュートリアルでは、基本的な Movie データベース アプリケーションをビルドします。 まず、可能な限り最速かつ最も簡単な方法で Movie データベース アプリケーションを作成します。 すべてのデータ アクセスは、コントローラー アクションから直接実行します。
次に、リポジトリ パターンを使用する方法について説明します。 リポジトリ パターンを使用するには、もう少し作業が必要です。 ただし、このパターンを採用する利点は、変更に適応でき、簡単にテストできるアプリケーションをビルドできることです。
モデル クラスとは
MVC モデルには、MVC ビューまたは MVC コントローラーに含まれていないすべてのアプリケーション ロジックが含まれています。 特に、MVC モデルには、すべてのアプリケーション ビジネスおよびデータ アクセス ロジックが含まれています。
さまざまなテクノロジを使用して、データ アクセス ロジックを実装できます。 たとえば、Microsoft Entity Framework、NHibernate、Subsonic、または ADO.NET クラスを使用して、データ アクセス クラスをビルドできます。
このチュートリアルでは、LINQ to SQL を使用してデータベースのクエリと更新を行います。 LINQ to SQL では、Microsoft SQL Server データベースを操作する非常に簡単な方法が提供されます。 ただし、ASP.NET MVC フレームワークは LINQ to SQL に関連付けられていないことを理解しておくことが重要です。 ASP.NET MVC は、あらゆるデータ アクセス テクノロジと互換性があります。
Movie データベースを作成する
このチュートリアルでは、モデル クラスをビルドする方法を説明するために、単純な Movie データベース アプリケーションをビルドします。 最初に新しいアプリケーションを作成します。 [ソリューション エクスプローラー] ウィンドウで App_Data フォルダーを右クリックし、メニュー オプション [追加]、[新規項目] を選択します。 [SQL Server データベース] テンプレートを選択し、「MoviesDB.mdf」という名前を付けて、[追加] ボタンをクリックします (図 1 を参照)。
図 01: 新しい SQL Server データベースの追加 (クリックするとフルサイズの画像が表示されます)
新しいデータベースを作成したら、App_Data フォルダー内の MoviesDB.mdf ファイルをダブルクリックしてデータベースを開くことができます。 MoviesDB.mdf ファイルをダブルクリックすると、サーバー エクスプローラー ウィンドウが開きます (図 2 を参照)。
Visual Web Developer を使用する場合、サーバー エクスプローラー ウィンドウはデータベース エクスプローラー ウィンドウと呼ばれます。
図 02: サーバー エクスプローラー ウィンドウの使用 (クリックするとフルサイズの画像が表示されます)
ムービーを表すテーブルをデータベースに 1 つ追加する必要があります。 [テーブル] フォルダーを右クリックし、メニュー オプション [新しいテーブルの追加] を選択します。 このメニュー オプションを選択すると、テーブル デザイナーが開きます (図 3 を参照)。
図 03: テーブル デザイナー (クリックするとフルサイズの画像が表示されます)
データベース テーブルに次の列を追加する必要があります。
列名 | [データ型] | [NULL を許容] |
---|---|---|
Id | int | False |
Title | Nvarchar(200) | False |
監督 | NVarchar(50) | False |
Id 列に対して 2 つの特別な操作を行う必要があります。 まず、テーブル デザイナーで列を選択し、キーのアイコンをクリックして、ID 列を主キー列としてマークする必要があります。 LINQ to SQL では、データベースに対して挿入または更新を実行するときに主キー列を指定する必要があります。
次に、Is Identity プロパティに [はい] の値を割り当てることで、Id 列を ID 列としてマークする必要があります (図 3 を参照)。 ID 列は、新しいデータ行をテーブルに追加するたびに、自動的に新しい番号が割り当てられる列です。
LINQ to SQL クラスを作成する
MVC モデルには、tblMovie データベース テーブルを表す LINQ to SQL クラスが含まれます。 これらの LINQ to SQL クラスを作成する最も簡単な方法は、[モデル] フォルダーを右クリックし、[追加]、[新しい項目] の順に選択し、LINQ to SQL クラス テンプレートを選択し、クラスに Movie.dbml という名前を付けて、[追加] ボタンをクリックすることです (図 4 を参照)。
図 04: LINQ to SQL クラスの作成 (クリックするとフルサイズの画像が表示されます)
Movie LINQ to SQL クラスを作成した直後に、オブジェクト リレーショナル デザイナーが表示されます。 サーバー エクスプローラー ウィンドウからオブジェクト リレーショナル デザイナーにデータベース テーブルをドラッグして、特定のデータベース テーブルを表す LINQ to SQL クラスを作成できます。 オブジェクト リレーショナル デザイナー上に tblMovie データベース テーブルを追加する必要があります (図 5 を参照)。
図 05: オブジェクト リレーショナル デザイナーの使用 (クリックするとフルサイズの画像が表示されます)
既定では、オブジェクト リレーショナル デザイナーは、デザイナーにドラッグするデータベース テーブルとまったく同じ名前のクラスを作成します。 ただし、このクラスを tblMovie
という名前にはしたくありません。 したがって、デザイナーでクラスの名前をクリックし、クラスの名前を Movie に変更します。
最後に、[保存] ボタン (フロッピーの画像) をクリックして LINQ to SQL クラスを保存します。 そうしないと、LINQ to SQL クラスはオブジェクト リレーショナル デザイナーによって生成されません。
コントローラー アクションでの LINQ to SQL の使用
LINQ to SQL クラスが用意されたので、これらのクラスを使用してデータベースからデータを取得できます。 このセクションでは、コントローラー アクション内で LINQ to SQL クラスを直接使用する方法について説明します。 TblMovies データベース テーブルのムービーの一覧を MVC ビューに表示します。
まず、HomeController クラスを変更する必要があります。 このクラスは、アプリケーションの [コントローラー] フォルダーにあります。 リスト 1 のクラスのようにクラスを変更します。
リスト 1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
var dataContext = new MovieDataContext();
var movies = from m in dataContext.Movies
select m;
return View(movies);
}
}
}
リスト 1 の中の Index()
アクションでは、LINQ to SQL の DataContext クラス (MovieDataContext
) を使用して MoviesDB
データベースを表します。 MoveDataContext
クラスは、Visual Studio オブジェクト リレーショナル デザイナーによって生成されました。
tblMovies
データベース テーブルからすべてのムービーを取得するために、DataContext に対して LINQ クエリが実行されます。 ムービーの一覧は、movies
という名前のローカル変数に割り当てられます。 最後に、ムービーの一覧がビュー データを介してビューに渡されます。
ムービーを表示するには、次にインデックス ビューを変更する必要があります。 Views\Home\
フォルダー内にインデックス ビューがあります。 リスト 2 のビューのようにインデックス ビューを更新します。
リスト 2 – Views\Home\Index.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<ul>
<% foreach (Movie m in (IEnumerable)ViewData.Model)
{ %>
<li> <%= m.Title %> </li>
<% } %>
</ul>
</asp:Content>
変更されたインデックス ビューには、ビューの上部に <%@ import namespace %>
ディレクティブが含まれていることに注目してください。 このディレクティブは MvcApplication1.Models namespace
をインポートします。 ビューの中で model
クラス (特に Movie
クラス) を操作するには、この名前空間が必要です。
リスト 2 の中のビューには、ViewData.Model
プロパティによって表されるすべての項目を反復処理する foreach
ループが含まれています。 Title
プロパティの値が movie
ごとに表示されます。
ViewData.Model
プロパティの値が IEnumerable
にキャストされていることに注目してください。 これは ViewData.Model
の内容をループするために必要です。 ここでのもう 1 つのオプションは、厳密に型指定された view
を作成することです。 厳密に型指定された view
を作成すると、ビューの分離コード クラス内の特定の型に ViewData.Model
プロパティをキャストします。
HomeController
クラスとインデックス ビューを変更した後にこのアプリケーションを実行すると、空白のページが表示されます。 空白のページが表示されるのは、tblMovies
データベース テーブル内にムービー レコードがないためです。
tblMovies
データベース テーブルにレコードを追加するには、[サーバー エクスプローラー] ウィンドウ (Visual Web Developer 内の [データベース エクスプローラー] ウィンドウ) 内で tblMovies
データベース テーブルを右クリックし、メニュー オプション [テーブル データの表示] を選択します。 表示されるグリッドを使用して movie
レコードを挿入できます (図 6 を参照)。
図 06: ムービーの挿入 (クリックするとフルサイズの画像が表示されます)
tblMovies
テーブルにいくつかのデータベース レコードを追加し、アプリケーションを実行すると、図 7 のページが表示されます。 すべてのムービー データベース レコードが箇条書きで表示されます。
図 07: インデックス ビューでムービーを表示する (クリックするとフルサイズの画像が表示されます)
リポジトリ パターンの使用
前のセクションでは、コントローラー アクション内で LINQ to SQL クラスを直接使用しました。 Index()
コントローラー アクションから直接 MovieDataContext
クラスを使用しました。 単純なアプリケーションの場合、この操作に問題はありません。 ただし、コントローラー クラスで LINQ to SQL を直接操作すると、より複雑なアプリケーションをビルドする必要があるときに問題が発生します。
コントローラー クラス内で LINQ to SQL を使用すると、将来的にデータ アクセス テクノロジを切り替えるのが困難になります。 たとえば、Microsoft LINQ to SQL を使用して、データ アクセス テクノロジとして Microsoft Entity Framework を使用するように切り替えることができます。 その場合は、アプリケーション内のデータベースにアクセスするすべてのコントローラーを書き換える必要があります。
コントローラー クラス内で LINQ to SQL を使用すると、アプリケーションの単体テストをビルドすることも困難になります。 通常、単体テストの実行時にデータベースと対話する必要はありません。 データベース サーバーではなく、単体テストを使用してアプリケーション ロジックをテストする必要があります。
将来の変更により適応可能で、より簡単にテストできる MVC アプリケーションをビルドするには、リポジトリ パターンの使用を検討する必要があります。 リポジトリ パターンを使用する場合は、すべてのデータベース アクセス ロジックを含む個別のリポジトリ クラスを作成します。
リポジトリ クラスを作成するときは、リポジトリ クラスによって使用されるすべてのメソッドを表すインターフェイスを作成します。 コントローラー内では、リポジトリではなくインターフェイスに対してコードを記述します。 そうすることで、将来、さまざまなデータ アクセス テクノロジを使用してリポジトリを実装できます。
リスト 3 の中のインターフェイスは IMovieRepository
という名前が付けられ、ListAll()
という名前が付いた 1 つのメソッドを表します。
リスト 3 – Models\IMovieRepository.cs
using System.Collections.Generic;
namespace MvcApplication1.Models
{
public interface IMovieRepository
{
IList<Movie> ListAll();
}
}
リスト 4 の中のリポジトリ クラスは、IMovieRepository
インターフェイスを実装します。 IMovieRepository
インターフェイスに必要なメソッドに対応する、ListAll()
という名前が付いたメソッドが含まれていることに注目してください。
リスト 4 – Models\MovieRepository.cs
using System.Collections.Generic;
using System.Linq;
namespace MvcApplication1.Models
{
public class MovieRepository : IMovieRepository
{
private MovieDataContext _dataContext;
public MovieRepository()
{
_dataContext = new MovieDataContext();
}
#region IMovieRepository Members
public IList<Movie> ListAll()
{
var movies = from m in _dataContext.Movies
select m;
return movies.ToList();
}
#endregion
}
}
最後に、リスト 5 の中の MoviesController
クラスはリポジトリ パターンを使用します。 LINQ to SQL クラスを直接使用しなくなりました。
リスト 5 – Controllers\MoviesController.cs
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MoviesController : Controller
{
private IMovieRepository _repository;
public MoviesController() : this(new MovieRepository())
{
}
public MoviesController(IMovieRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.ListAll());
}
}
}
リスト 5 の中の MoviesController
クラスには 2 つのコンストラクターがあることに注目してください。 最初のコンストラクター (パラメーターなしのコンストラクター) は、アプリケーションの実行中に呼び出されます。 このコンストラクターは、MovieRepository
クラスのインスタンスを作成し、それを 2 番目のコンストラクターに渡します。
2 番目のコンストラクターには、IMovieRepository
パラメータという 1 つのパラメータがあります。 このコンストラクターは、パラメータの値を _repository
という名前のクラス レベルのフィールドに割り当てるだけです。
この MoviesController
クラスでは、依存関係の挿入パターンと呼ばれるソフトウェア設計パターンを利用しています。 特に、コンストラクターの依存関係の挿入と呼ばれるものを使用しています。 このパターンの詳細については、Martin Fowler の次の記事を参照してください。
http://martinfowler.com/articles/injection.html
MoviesController
クラス内のすべてのコード (最初のコンストラクターを除く) が、実際の MovieRepository
クラスではなく IMovieRepository
インターフェイスとやりとりしていることに注目してください。 コードは、インターフェイスの具体的な実装ではなく、抽象インターフェイスと対話します。
このアプリケーションで使用されるデータ アクセス テクノロジを変更する場合は、代替のデータベース アクセス テクノロジを使用するクラスで、IMovieRepository
インターフェイスを実装するだけで済みます。 たとえば、EntityFrameworkMovieRepository
クラスまたは SubSonicMovieRepository
クラスを作成できます。 コントローラー クラスはインターフェイスに対してプログラミングされるため、コントローラー クラスに IMovieRepository
の新しい実装を渡すことができ、そしてこのクラスは引き続き機能します。
さらに、MoviesController
クラスをテストする場合は、フェイクのムービー リポジトリ クラスを HomeController
に渡すことができます。 IMovieRepository
クラスは、実際にはデータベースにアクセスせず、ただし IMovieRepository
インターフェイスの必要なすべてのメソッドを含むクラスを使用して実装できます。 そうすることで、本物のデータベースに実際にアクセスすることなく、MoviesController
クラスの単体テストを実施できます。
まとめ
このチュートリアルの目的は、Microsoft LINQ to SQL を利用して MVC モデル クラスを作成する方法を示すことでした。 ASP.NET MVC アプリケーションでデータベース データを表示するための 2 つの戦略を検討しました。 まず、LINQ to SQL クラスを作成し、コントローラー アクション内で直接クラスを使用しました。 コントローラー内で LINQ to SQL クラスを使用すると、MVC アプリケーションでデータベース データをすばやく簡単に表示できます。
次に、難易度が少し上がるものの、より優れたデータベース データを表示するためのパスについて説明しました。 リポジトリ パターンを利用し、すべてのデータベース アクセス ロジックを別のリポジトリ クラスに配置しました。 コントローラーでは、具象クラスではなく、インターフェイスに対してすべてのコードを記述しました。 リポジトリ パターンの利点は、将来的にデータベース アクセス テクノロジを簡単に変更でき、コントローラー クラスを簡単にテストできる点です。