株式会社インデペンデンスシステムズ横浜

システム開発エンジニアの西田五郎が運営しております。Raspberry Pi や Arduino その他新規開発案件のご依頼をお待ちしております。

ASP.NET

ASP.NET Web APIでデータ蓄積(その2)ASP.NET コードファーストでのモデル構築

投稿日:2015年7月24日 更新日:

ASP.NET Web APIでデータ蓄積の2回目です。前回は、ASP.NET Web APIについて概要的なことを書きました。今回から実際にデータ蓄積アプリ的なものを構築しますが前回の最後に書いた通りMVCに分けて順番に書いていきたいと思います。今回はMVCのMでモデル構築についてです。そのモデル構築をMicrosoftのEntity Frameworkのコードファーストの技法を使って作成します。

コードファースト(Code First)とは
ここでのコードファーストとはMicrosoftのEntity Frameworkの開発方法でコード(プログラム言語でのクラス)でモデルを定義してそこからデータベースが生成されて開発を進める方法です。今回のコードファーストが一番新しい方法ですが他の方法としては以下の方法があります。
・データベースファースト
・モデルファースト

要するに実際の開発を何から始めるかということです。以下のようになります。
・データベースファースト – 実際のデータベースを作成して個々のテーブルを作成する。そこからモデルを生成する。
・モデルファースト – Entity Framework デザイナーを使用してモデルを作成する。そこからデータベースを生成する。

私の場合ですが、何といっても今だにデータベースファーストが主流です。この場合ですが、データベースの変更をしたり、追加したりするとその都度モデルを再生成してそこから実際のロジックのプログラミングとなります。

これが、コードファーストの場合はモデルのコードを変更、追加していけばそれに応じてデータベースも変更されるためデータベースファーストの手順より効率がいいということになります。

但しですが、ある程度実際に生成されるデータベースがイメージ出来ないとモデルのコードも書けないと思います。あと実際のデータベースのリレーションや制約もコード上に記述するのでこれらの書き方を習得する必要があります。また単独で開発する場合はともかく、複数で開発を並行して行う場合は、モデル変更の同期が取りずらい場合もあるかもしれないです。

実際のコードファーストでの開発
ということで実際にやってみます。ここではC#のコンソールアプリケーションでコードファーストのみに注目して作業します。まずコンソールアプリケーションを生成します。

実際のプロジェクト一式は以下です。(※単なるサンプルプログラムです。ご利用による不具合、不利益等について弊社は一切責任を負わないものとします。)
Visual Studio Community 2013でのプロジェクト一式

Visual Studio(ここでは Visual Studio Commnunity 2013です。) でプロジェクトを作成します。
[ファイル] -> [新規作成] -> [プロジェクト] の順にクリックします。
以下のようにC#でコンソールアプリケーションのプロジェクトを作成します。プロジェクト名は任意のプロジェクト名でいいです。
0001

Entity Frameworkを追加します。
[ツール] -> [NuGetパッケージマネージャー] -> [ソリューションのNuGetパッケージの管理]の順にクリックします。Entity Frameworkを検索してインストールします。
0003

0005

以上で準備が完了です。

実際にコードを書きます。以下のusingを追加しておきます。

using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

コードファーストとなるモデルのクラスを追加します。通常はモデルのファイルを作成しますが、ここでは、Program.csに書きます。Programクラスに以下を追加しました。

    /// <summary>
    /// センサーデバイス
    /// </summary>
    public class SensorDevice
    {
        public int Id { get; set; }

        [Required]
        public int DeviceId { get; set; }

        [Required]
        [MaxLength(20), MinLength(5)] 
        public string DeviceName { get; set; }
    }

    /// <summary>
    /// 温度データ
    /// </summary>
    public class Temperature
    {
        public int Id { get; set; }

        [Required] 
        public int DeviceId { get; set; }

        [Required]
        public double TemperatureValue { get; set; }
    }

温度センサーデバイスから送信された温度データを蓄積するというイメージです。温度センサーデバイスとそのセンサーから送信される温度データのモデルをイメージしました。

モデル自体は単純なクラスです。(※これをPOCO(「Plain Old CLR Object」の略で、特別なクラスやインターフェイスの継承/実装を行っていないクラス)と呼んでいるようです。)プロパティと注釈(Annotation)で構成されます。注釈を使う場合は、System.ComponentModel.DataAnnotationsが必要です。ここでは、必須項目と長さの制限を書いてみました。

このように単純なクラスでコードファーストとなるモデルが記述出来るということですが、このモデルがどのようにテーブル定義のフィールドや制約に反映されるかが想像出来ないと書きにくいと思います。後でモデルからデータベースが生成出来たら、実際に生成されたテーブルも確認してみます。

次に、データベースとのセッションを表すコンテキスト定義を記述します。このコンテキストによって、クエリの実行とデータの保存が可能になります。これには、System.Data.Entityが必要です。ここでは以下のように定義しました。DbContextを定義してモデル内のそれぞれの型に対応する DbSet をpublicで公開するというのが基本的な書き方のようです。

  /// <summary>
    /// DBコンテキスト
    /// </summary>
    class TemperatureDbContext : DbContext
    {
        public DbSet<SensorDevice> SensorDevices { get; set; }
        public DbSet<Temperature> Temperature { get; set; }
    }

これでモデルは完了です。このモデルでデータを作成する処理をmainに書いてみます。

static void Main(string[] args)
    {
        //DBコンテキスト生成
        TemperatureDbContext dbcn = new TemperatureDbContext();

        //デバイスを2個追加
        SensorDevice dev1 = new SensorDevice { DeviceId = 1, DeviceName = "DevName01" };
        SensorDevice dev2 = new SensorDevice { DeviceId = 2, DeviceName = "DevName02" };

        dbcn.SensorDevices.Add(dev1);
        dbcn.SensorDevices.Add(dev2);

        //温度データを2件追加
        Temperature temp1 = new Temperature { DeviceId = 1, TemperatureValue = 21.1 };
        Temperature temp2 = new Temperature { DeviceId = 2, TemperatureValue = 22.3 };

        dbcn.Temperature.Add(temp1);
        dbcn.Temperature.Add(temp2);

     //変更の反映
     dbcn.SaveChanges(); 
    }

まず、try catchもusing()もここでは省略していますのでご了承ください。それから、追加処理しか書いていなので実際に生成されたDBでデータを確認することにします。追加処理の際にIdのプロパティには何も設定していないですが、Idというプロパティは自動で設定される仕様のようです。

ここまででビルドしてエラーがなければ実行します。エラーがなければ何も表示されず実行が完了します。

データベースの確認
Visual Studioから、[表示] -> [SQL Server オブジェクトエクスプローラー]で SQLServer オブジェクトエクスプローラーを開きます。
0007

(localdb)に作成されているはずです。このように複数のlocaldbがある場合はVisual Studioで作成したプロジェクト名+データベースコンテキスト名を探します。

まず、以下のようにテーブルが確認出来ました。
0008

データも以下のように確認出来ました。
0009

0011

今度はこのデータを読み込みます。mainを以下のように書き換えました。エラー処理は書いていません。

  static void Main(string[] args)
        {
            //DBコンテキスト生成
            TemperatureDbContext dbcn = new TemperatureDbContext();

            //デバイスを表示
            foreach (var dev in dbcn.SensorDevices)
            {
                Console.WriteLine(dev.DeviceId.ToString() + ":" + dev.DeviceName);
            }

            Console.WriteLine();

            //温度を表示
            foreach (var tmp in dbcn.Temperature)
            {
                Console.WriteLine(tmp.TemperatureValue.ToString() + ":" + tmp.DeviceId.ToString());
            }

            Console.WriteLine();

            //温度データとデバイスをJoin
            var query = dbcn.Temperature.Join(
                dbcn.SensorDevices,
                tm => tm.DeviceId,
                dv => dv.DeviceId,
                (tm, dv) => new { tm.TemperatureValue, dv.DeviceId, dv.DeviceName } ).Select(itm => itm);

            //温度データを表示
            foreach(var dat in query)
            {
                Console.WriteLine(dat.TemperatureValue.ToString() + " " + dat.DeviceId.ToString() + " " + dat.DeviceName);
            }
}

実行すると以下のように表示されました。
0012

モデルの変更と確認
次にモデルを更新したい場合の作業です。まずモデルを変更します。ここでは以下のようにOwnerNameというプロパティを追加してみました。

    /// <summary>
    /// センサーデバイス
    /// </summary>
    public class SensorDevice
    {
        public int Id { get; set; }

        [Required]
        public int DeviceId { get; set; }

        [Required]
        [MaxLength(20), MinLength(5)] 
        public string DeviceName { get; set; }

        [Required]
        [MaxLength(20), MinLength(5)]
        public string OwnerName { get; set; }
    }

mainで以下のようにこのプロパティにデータを追加します。

static void Main(string[] args)
{
    //DBコンテキスト生成
    TemperatureDbContext dbcn = new TemperatureDbContext();

    foreach(var device in dbcn.SensorDevices)
    {
        device.OwnerName = "owner" + device.DeviceId.ToString();
    }

    //変更の反映
    dbcn.SaveChanges();
}

実行する前に、データベースの更新(マイグレーション)を自動で実行出来るように設定します。
[ツール] -> [NuGetパッケージマネージャー] -> [パッケージマネージャーコンソール]でパッケージマネージャーコンソールを起動します。そして以下を入力します。
PM> Enable-Migrations -EnableAutomaticMigrations

以下のような結果が返ります。
Checking if the context targets an existing database…
Code First Migrations enabled for project EntityFrameworkCodeFirst1.

次にデータベースを更新します。パッケージマネージャーコンソールで以下を入力します。
PM> Update-Database

以下のような結果が返ります。
Specify the ‘-Verbose’ flag to view the SQL statements being applied to the target database.
No pending explicit migrations.
Applying automatic migration: 201507111247428_AutomaticMigration.
Running Seed method.

これでプロジェクトにMigrationsというフォルダが出来ますが、このあたりはまた次回以降に取り組みたいと思います。

ここで、作成した追加のプロパティにデータを追加するプログラムを実行します。問題がなければ特に何も表示されないで終了します。

テーブルとデータを確認します。以下のようにフィールドが追加されていてデータも確認出来ました。
0014

0015

以上がコードファーストでのモデル作成からデータ操作、モデル変更までについてです。

今回はここまでです。次回は、ASP.NET ApiControllerクラスについてです。

今回のシリーズの一覧です。
ASP.NET Web APIでデータ蓄積(その1)ASP.NET Web APIとは
ASP.NET Web APIでデータ蓄積(その2)ASP.NET コードファーストでのモデル構築
ASP.NET Web APIでデータ蓄積(その3)ASP.NET ApiControllerクラス
ASP.NET Web APIでデータ蓄積(その4)ASP.NET ApiControllerクラスとView
ASP.NET Web APIでデータ蓄積(その5)ASP.NET Web APIテンプレートからの構築
ASP.NET Web APIでデータ蓄積(その6)ASP.NET Web APIでの動作確認
ASP.NET Web APIでデータ蓄積(その7)Raspbery Piからの温度データ蓄積

その他関連サイト
Getting Started with ASP.NET Web API 2 (C#)
Using Web API 2 with Entity Framework 6
Entity Framework Code First の規約
Entity Framework Code First のデータ注釈
Entity Framework での新しいデータベース向けの Code First

Amazon関連商品

AdSense

AdSense

-ASP.NET

執筆者:

関連記事

ASP.NET Web APIでデータ蓄積(その1)ASP.NET Web APIとは

ASP.NET Web APIを利用してデータを蓄積する機能を実装してみたいと思います。漠然とデータ蓄積といってもいろいろなデータがあると思いますが、ここではセンサー等のデバイスから自動的に送信された …

no image

ASP.NETユーザ管理(その4)ユーザ情報の追加

ASP.NETユーザ管理(ASP.NET Identityフレームワーク)の4回目です。前回は、ユーザ登録時にメールを送信する方法を確認しました。今回は、WebFormsのテンプレートで、ユーザ登録時 …

no image

ASP.NETユーザ管理(その9) パスワードのリセット

ASP.NETユーザ管理(ASP.NET Identityフレームワーク)の9回目です。前回は、2要素認証を使ってみました。今回はパスワードリセットです。パスワードリセットですが、要するにパスワードを …

ASP.NET Web APIでデータ蓄積(その7)Raspbery Piからの温度データ蓄積

ASP.NET Web APIでデータ蓄積の7回目です。前回までで少なくとも温度データが登録出来るASP.NET Web APIが出来ました。今回はRaspbery Piに実際に温度センサを接続して温 …

no image

ASP.NETユーザ管理(その2)WebFormsでのASP.NET Identity

ASP.NETユーザ管理の2回目です。前回は、主にASP.NET Identityとはといった概要的な内容について書きました。今回から実際に動作させながら確認します。 WebFormsのテンプレートを …