CodeZine(コードジン)

特集ページ一覧

Entity FrameworkとLINQで快適DBプログラミング

Visual StudioでDB連携も簡単プログラミング ~知っておきたいLINQメソッド式&ラムダ式 第1回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2014/12/26 14:00
目次

データベースの準備

 それでは、本題となるデータベースのクエリ処理に入るにあたり、データベースを準備します。今回はEntity Framework Code Firstを使います。Entity Framework Code Firstとは、データベースアクセスのためのフレームワークで、データベースのテーブルやフィールドをC#のクラスやプロパティとして定義し、そのクラスに対する操作を行うことで、ソースコード中にSQLを直接埋め込むことなく、データベース操作を行えるフレームワークです。詳細については前述の解説記事をご覧ください。

 今回は、図2のような、商品(Products)、出荷元(Makers)、担当者(Employees)、部署(Departments)の4つのテーブルを使います。また、初期データもソースコードから投入します。

図2 ER図。今回使用する4つのテーブル
図2 ER図。今回使用する4つのテーブル

 まず、Visual Studio 2013を起動して新しいプロジェクトを作成し[Windows デスクトップ]‐[コンソール アプリケーション]を選択します。次いで[プロジェクト]‐[新しい項目の追加]より[ADO.NET Entity Data Model]を追加しましょう。名前は[CodeZineSampleContext]とします(図3)。

図3 [ADO.NET Entity Data Model]の追加
図3 [ADO.NET Entity Data Model]の追加

 続いて、モデルの種類として[空のCode Firstモデル]を指定します(図4)。

図4 [空のCode Firstモデル]を指定
図4 [空のCode Firstモデル]を指定

エンティティの定義

 プロジェクトにCodeZineSampleContext.csが追加されます。まず、使用するテーブルを定義しましょう。Entity Framework Code Firstでは、ソースコードとデータベースが表1のように綺麗に対応しています。

表1 Entity Framework Code Firstにおけるソースコードとデータベースの対応関係
ソースコード データベース 備考
クラス定義 テーブル定義 テーブルに対応するクラスはエンティティと呼ばれる
エンティティのインスタンス テーブルの1レコード
数値、文字列、日時などの基本型プロパティ テーブルのフィールド C#のデータ型に対応するデータベースのデータ型が使用される
他のエンティティ型のプロパティ 関連するテーブルへのリレーション ナビゲーションプロパティと呼ばれる特殊なプロパティ。ICollectionを使うと1対多関係となる。virtualとして宣言すると遅延ローディング(第3回で解説)が有効になる

 先ほどのER図に合わせて、リスト4のように使用するエンティティの定義を追加します。ここでは、今回使用する商品、担当者、部署、出荷元のエンティティを定義し、必要なフィールドをプロパティとして定義し、関連するリレーションをナビゲーションプロパティとして定義しています。

リスト4 エンティティ定義 - CodeZineSampleContext.cs
public class Product //商品
{
    public int Id { get; set; } //プライマリキー
    public string Name { get; set; } //商品名
    public int Price { get; set; } //金額
    public virtual Maker Maker { get; set; } //出荷元
    public virtual Employee Employee { get; set; } //商品担当者
}

public class Employee //担当者
{
    public int Id { get; set; } //プライマリキー
    public string Name { get; set; }//担当者名
    public DateTime Birthday { get; set; }//誕生日
    public virtual Department Department { get; set; } //所属部署
    //担当する商品一覧。ICollectionを使って1対多関係を表現
    public ICollection<Product> Products { get; set; }
}

public class Department //部署
{
    public int Id { get; set; } //プライマリキー
    public string Name { get; set; } //部署名
    public ICollection<Employee> Employees { get; set; } //部署内担当者一覧
}

public class Maker //出荷元
{
    public int Id { get; set; } //プライマリキー
    public string Name { get; set; } //会社名
    public virtual ICollection<Product> Products { get; set; } //出荷商品一覧
}

コンテキストクラスの定義

 また、Entity Frameworkの作法では、コンテキストクラスと呼ばれるクラスがデータベースアクセスの基本となります。コンテキストクラスにはエンティティのDbSet(=エンティティの一覧を表すクラス。データベースのテーブルに相当)を定義する必要がありますので、今回のコンテキストクラスであるCodeZineSampleContextのプロパティに定義したエンティティのDbSetを追加します(リスト5)。

リスト5 エンティティのDbSetを追加 - CodeZineSampleContext.cs
public class CodeZineSampleContext : DbContext
{
・・・
    //コンテキストクラスのプロパティで各エンティティのDbSetを持っておく
    public virtual DbSet<Employee> Employees { get; set; }
    public virtual DbSet<Department> Departments { get; set; }
    public virtual DbSet<Product> Products { get; set; }
    public virtual DbSet<Maker> Makers { get; set; }
}

データの挿入

 続いて、リスト6のようなコードで、データベースにデータを挿入します。挿入方法の詳細はサンプルを参照してください。サンプルでは、クエリ対象として5個ほどの商品(Product)データと、それに関連する担当者、部署、出荷元データを挿入しています。

リスト6 データを挿入 - Program.cs
var department1 = new Department() //部署を作成
{
    Name = "営業部"
};
var employee1 = new Employee() //担当者を作成
{
    Name = "土井",
    Birthday = DateTime.Parse("1978-10-25"),
    //(1)この担当者の部署は「営業部」
    Department = department1
};
var maker1 = new Maker()     //出荷元
{
    Name = "お菓子屋さんA"
};

var product1 = new Product() //商品定義
{
    Name = "ショートケーキ",
    Price = 250,
    Maker = maker1,          //出荷元は「お菓子屋さんA」
    Employee = employee1,    //担当者は「土井」
};
//商品を登録(関連するエンティティも自動的に登録される)
context.Products.Add(product1);
・・・
//保存
context.SaveChanges();

 ここで作成しているdepartment1、employee1、maker1、product1などはテーブルのレコードに相当し、それぞれのオブジェクトのプロパティはレコードのフィールドに相当します。また、他のテーブルへのリレーションもプロパティで指定します。

 たとえば、(1)ではemployee1のDepartmentプロパティに、上で作成したdepartment1を設定しています。これは、担当者「土井」は「営業部」という部署に所属するという関係になります。実際のデータベース上では、EmployeesテーブルのDepartment_IdフィールドにDepeartmentsテーブルのIdフィールドの値が設定されます(図5、図6)。

図5 Departmentsテーブルの実際の値。営業部のIdは1
図5 Departmentsテーブルの実際の値。営業部のIdは1
図6 Employeesテーブルの実際の値。営業部所属なのでDepartment_Idが1となる
図6 Employeesテーブルの実際の値。営業部所属なのでDepartment_Idが1となる

まとめ

 今回はLINQとラムダ式の概要を解説しました。やや特殊な記法のLINQクエリ式に比べて、メソッドを連ねていくメソッド式は比較的なじみやすいと感じられたのではないでしょうか。また、Entity Framework Code Firstを使ってクエリ対象のデータベースも準備しました。

 次回は「LINQメソッド式を使ってみよう」と題して、実際にLINQメソッド式を使ったクエリについて解説します。お楽しみに。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

修正履歴

  • 2015/01/05 17:38 タイトル周りを修正しました。

バックナンバー

連載:Visual StudioでDB連携も簡単プログラミング ~知っておきたいLINQメソッド式&ラムダ式

著者プロフィール

  • WINGSプロジェクト 土井 毅(ドイ ツヨシ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5