アーキテクチャをスマートに。

株式会社ネオジニア代表。ITアーキテクトとしてのお仕事や考えていることなどをたまに綴っています。(記事の内容は個人の見解に基づくものであり、所属組織を代表するものではありません)

ASP.NET MVC 4 ことはじめ(5)モデルと足場

ASP.NET MVC は、実はモデルに相当する部分を提供していません。既存のDBアクセス技術である Entity Framework を組み合わせて使用します。

Visual Studio 2012 で ASP.NET MVC 4 のプロジェクトを新規作成すると Entity Framework 5.0 がデフォルトで使えるようになってて、いま流行りのコードファーストが出来ます。Railsパクリ(!?)のお手軽 Scaffolding もバッチリやってくれます。
この辺がすごい強力で楽チンだと思います。

Code First

コードファーストなので、DBにテーブルを作る前にいきなりモデルクラスから作り始めます。
モデルクラスとは、DBのテーブルの1レコードに対応する構造体みたいなイメージです。(厳密には、DBだけじゃなくて様々なモデルクラスが考えられるので、区別のためにデータモデルのことをエンティティと言うこともあります)

ここでは、簡単な経費精算データベースを作ってみましょう。

ではエンティティクラスを作っていきます。(以下、前回のHelloWorldプロジェクトの続きから作業していますが、エンティティの作り方には関係ないので、新規プロジェクトでやっても同じです)
ソリューションエクスプローラにて「Model」フォルダ上で右クリックし、[追加]→[クラス] を選択します。

クラス名は何でもよいですが、あとでテーブル名になりますのでその辺を考慮して命名します。英単語の単数形がクラス名、複数形がテーブル名になる、という暗黙のルールがあります。(CoC:設定より規約、の精神です)
ここでは分かりやすく「KeihiDetail」としました。

クラスが作成されたら、メンバを定義していきます。要するにDBのテーブル設計をしていくわけです。テーブルの各項目をクラスのプロパティとして定義していく、という解釈で良いと思います。
KeihiDetailテーブル設計は、とりあえずこんな内容で考えています*1

項目
日付 DateTime
内容 Varchar
支払先 Varchar
金額 Integer
備考 Varchar

これをプロパティとして定義していくのですが、次のような注意点というかルールがあります。

  • public な プロパティとして定義すること(もちろんゲッター、セッターも)
  • 主キー項目名は、クラス名+"Id" とすること
  • コンストラクタは書かなくてもよいが、書く場合は引数なしのコンストラクタ(=デフォルトコンストラクタ)が必須

で以下のようになりました。(主キーが必要なので先の表から項目を追加しています)
Models/KeihiDetail.cs

using System;

namespace HelloWorld1.Models
{
    public class KeihiDetail
    {
        public int KeihiDetailId { get; set; }  // 主キー

        public DateTime Dt { get; set; }  // 日付

        public string Subject { get; set; }  // 内容

        public string Payee { get; set; }  // 支払先

        public int Amount { get; set; }  // 金額

        public string Remark { get; set; }  // 備考
    }
}

Context

エンティティクラスを作ったら、これらを実際のDB接続に割り当てるためのコンテキストクラスを作ります。
これは Entity Framework でのお作法があるので、その通りに書くだけです。

  • とりあえず using System.Data.Entity; する
  • DbContext クラスを継承する
  • public DbSet<エンティティクラス名> テーブル名 { get; set; } としてプロパティ定義する
  • テーブル名は、エンティティクラス名の複数形

ぜんぜん難しくないです。慣れればごく自然に見えてきます。

クラス名はとくにルールはないです。ここでは「KeihiContext」としました。(後々 Web.config で接続先をカスタマイズすることになるので、どのDB接続かが分かるような名前がいいのかも)
Models/KeihiContext.cs

using System.Data.Entity;

namespace HelloWorld1.Models
{
    public class KeihiContext : DbContext
    {
        public DbSet<KeihiDetail> KeihiMeisais { get; set; }
    }
}

エンティティクラス1つに対応したプロパティが1つ、というイメージです。要するにテーブルの一覧です。テーブルを増やしたければ、その都度エンティティクラスを書いてコンテキストクラスにプロパティを追加すればよい、というわけです。

ここまで書けばあとはO/Rマッピングがやってくれるので、もういきなりDBアクセスのコードが書けます。SQL でいちいち CREATE TABLE したりマッピング定義のXML書いたりしなくてもいいんです!*2

Scaffolding

せっかくなので ASP.NET MVC の超便利機能「Scaffolding」をやってみましょう。Scaffolding (スキャフォールディング)とは「足場」という意味で、Rails由来のソースコード自動生成の仕組みです。モデルクラスに対応したコントローラとビューを自動生成してくれます。

やりかたは簡単。モデルクラス(エンティティクラス)を作ったら、一旦ビルドしておきます。(ビルドを通さないとモデルを認識しない)
そしてコントローラの新規作成をします。

ダイアログ「コントローラーの追加」が表示されて、「スキャフォールディングのオプション」を設定すればいいんです。テンプレートは「Entity Frameworkを使用した…MVCコントローラー」でいきましょう。モデルクラスとデータコンテキストクラスには対象のクラスをプルダウンから選択しておきます。

コントローラ名は「KeihiTestController」としました。
これで「追加」ボタンを押すと、コントローラとビューが自動生成されます。

もしエラーになった場合は、エンティティクラスの作り方が間違ってないか、再確認してください。特に主キー項目の名称に暗黙のルールがあるのでリファクタリングしたときに注意が必要です。あとはコンテキストクラスのテーブル名にも暗黙のルールがあります。

無事に自動生成されたら、F5を押して実行してみましょう。ブラウザが表示されたら、URLを手入力して今作ったコントローラにアクセスします。

 http://localhost:53280/KeihiTest  (ポート番号は環境によって変わります)

Indexアクションでデータの一覧が表示されるのですが、最初は何もデータがないです。

「Create New」をクリックすればデータ登録フォームが表示されます。何か登録してみましょう。

実際に動かしてみるとわかりますが、入力内容のチェックも自動的にやってくれます。素晴らしい!この入力チェックも、ロジックで実装しなくてもエンティティにアノテーションを書いていけば自動的にやってくれます。*3
主キー項目はシステム内部での管理項目となるので、手入力するためのフィールドは生成されないのが正解です。
2件ほどデータ登録するとこんな感じになりました。

Edit, Details, Delete の動きも確認してみてください。
自動生成されたコントローラを見れば、どういう作りになってるか参考になると思います。

あとはこの足場をベースに手直ししながら作り進めていく、という感じです。そのための足場なんですね。ちょっとしたマスタメンテならもうほとんどこれで出来ます。

とっつきにくい?

僕もそうでしたが、Rails未経験だと「便利そうなのはわかる」けど、そのための、これまでなかった「暗黙のルール」があるために逆にとっつきにくいのかもしれません。
これまでのASP.NETとはパラダイムが違う、ということを理解しないといけないです。
ASP.NETASP.NET MVC に限った話ではなく一般論ですが、Rails以前は開発者が望む動作をさせるために、フレームワークに対していろいろな設定をしてカスタマイズしていく、という考え方だったと思います。ところがいくつかのフレームワークを組み合わせたり、それらが多機能化して設定ファイルが複雑化、巨大化していき、大量の設定項目を管理しなければならず、すごく大変になってきたわけです。それを解決するために出てきたのがRailsであり「CoC:設定より規約」という考え方(パラダイム)です。
CoCアプローチをとった(Railsライクな)フレームワークでは、フレームワークが用意する仕組みに則ってアプリケーションを設計構築すれば、面倒な設定ファイルの類をほとんど書かなくていいんです。フレームワークが用意している仕組みやルールを変えたい時だけ、カスタマイズ設定をすればよいわけです。フレームワークのお作法に反するような設計は、工数を増やすだけなので避けるべきです。
なので、まずは新しいパラダイムフレームワークのお作法を知ることが重要です。そして、フレームワークを使って出来ること、出来ないことを判断できるようになることが先決です。
そうすれば、Railsライクなフレームワークの得意分野がわかり、どう活用すればよいかがわかるようになります。慣れてくれば、アプリケーションの設計構築にかかる時間を大幅に減らすことが出来ると思います。

*1:あまり深く考えすぎず、頭に浮かんだ構造をとりあえずそのままコーディングしていきます。後からいくらでも簡単に変更できますので。そのためのコードファーストです

*2:DB接続の定義はすでに Web.config に書かれていて、SQL Server Compact を使う記述がデフォルトで入ってます

*3:アノテーション検証」でググってみてください