かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

全然話題として触れてこなかったけど実は凄く注目してるEntity Framework Code Firstを試してみたよ

ず〜〜〜〜〜っと静観してたEntity FrameworkのCode Firstですが、実はひそかにイケてる子だとずっと信じてました。今回、あるきっかけがあったので試してみました!
あるきっかけと言うのは、Web Platform InstallerでASP.NET MVC3をインストールしたついでに入ってきたNuGetのことです。

NuGetは簡単に言うと、JavaでいうMavenや、RubyでいうGemや、PerlでいうCPANみたいな感じで外部のライブラリを手軽にダウンロードして使えるように設定してくれる嬉しいやつです。(Mavenはビルドシステムだからライブラリの依存関係見てくれるだけじゃないけど)

インストールすると、Visual Studioのツールメニューに以下のような感じで追加されます。コマンドライン強者はコンソール使えばいいと思うけど、私はGUIラブなCUI弱者なのでAdd Library Package Referenceを愛用しそうです。


検索もできて、ダウンロードもしてくれて、参照も追加してくれる。至れり尽くせりです。

本題のCodeFirst

ということで、早速CodeFirstを試してみようと思います。今回は、超簡単なデータでCRUDするところまでやってみます。因みにDBはSQL Server 2008 Express Editionを使用してます。


ということで早速プロジェクトを作成します。簡単に試すだけなのでConsoleApplicationを新規作成します。プロジェクト名は「HelloCodeFirst」にしました。
ツールメニューからLibrary Package Manager → Add Library Package Referenceを選びます。Onlineを選択してCodeFirstで検索すると検索結果に目当てのブツが表示されます。

Installボタンをぽちっとすると、勝手にダウンロードからインストールまでしてくれます。
因みに、ここでインストールとしたライブラリはソリューションフォルダのpackagesというフォルダに追加されます。

あと、ちょっと残念なのですが手動でSystem.Data.Entityを参照追加して準備完了です。

エンテティの定義

さて、ここからがコードファーストの素敵な所です。DBの定義?そんなの知ったこっちゃありません!コード書いちゃいましょう。ということで、以下のようなコードを書きます。一般的な従業員と部署の関係ですね。

namespace HelloCodeFirst
{
    using System.Collections.Generic;

    public class Employee
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public virtual ICollection<Department> Departments { get; set; }
    }

    public class Department
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public virtual Employee Employee { get; set; }
    }

}

これでOKです。気を付ける所は、主キーが〜IDとかいう名前じゃないといけない(ほかにもOKな名前あったと思うけど忘れた後で調べよう)とか、複数のエンテティ間の関連を表すプロパティ(ここでいうEmployeeのDepartmentsプロパティや、DepartmentのEmployeeプロパティ)は、virtualじゃないといけないという所です。
これさえ気を付ければエンテティの定義は普通のクラス定義と変わりありません。

Contextの定義

さて次はContextを作っていきます。これもコードでシンプルにさっくり作ります。こいつは、System.Data.Entity.DbContextを継承して、さっき定義した型を扱うためのプロパティをSystem.Data.Entity.IDbSetで定義してやるだけでOKです。

namespace HelloCodeFirst
{
    using System.Data.Entity;

    public class EduContext : DbContext
    {
        public IDbSet<Employee> Employees { get; set; }

        public IDbSet<Department> Departments { get; set; }
    }
}

さっそくCRUDしてみよう

ということで、さくっとCRUDする簡単なサンプルをMainメソッドに書きます。

namespace HelloCodeFirst
{
    using System;
    using System.Data.Entity.Database;
    using System.Linq;
    using System.Data.Entity;

    class Program
    {
        static void Main(string[] args)
        {
            int deptId;

            using (var ctx = new EduContext())
            {
                // Create
                {
                    var dept = ctx.Departments.Create();
                    dept.Name = "人事課";
                    // Addを忘れずに
                    ctx.Departments.Add(dept);

                    var emp = ctx.Employees.Create();
                    emp.Name = "田中 太郎";
                    // Addを忘れずに
                    ctx.Employees.Add(emp);

                    emp.Department = dept;
                    // SaveChangesで変更をDBに反映
                    ctx.SaveChanges();

                    // IDは自動生成されるので生成されたIDをとっておく
                    deptId = dept.ID;
                }

                // Read
                {
                    // LINQでとってこれる
                    foreach (var dept in ctx.Departments.Where(d => d.ID == deptId))
                    {
                        Console.WriteLine(dept.Name);
                        foreach (var emp in dept.Employees)
                        {
                            Console.WriteLine(emp.Name);
                        }
                    }
                }

                // Update
                {
                    var emp = ctx.Employees.First();
                    emp.Name = "木村 花子";
                    // SaveChangesで変更をDBに反映
                    ctx.SaveChanges();

                    // 更新結果を確認
                    Console.WriteLine(ctx.Employees.First().Name);
                }

                // Delete
                {
                    // 作った部署をRemoveで消す
                    var dept = ctx.Departments.First(d => d.ID = deptId);
                    ctx.Departments.Remove(dept);

                    var emp = ctx.Employees.First();
                    ctx.Employees.Remove(emp);

                    // SaveChangesで変更をDBに反映
                    ctx.SaveChanges();
                }
            }
        }
    }
}

ちょっと長いですが、純粋にコレクションの操作や今までのEntityFrameworkにあったSaveChangesを呼んでるのと同じです。
実行結果は以下のようになります。

きちんと読み取ったデータも表示されてるし、更新した結果も表示されています。

DBはどこじゃ

ということで気になるDBですが、勝手に作られてます。これもCodeFirstの規約に従った名前で作られるみたいです。

とりあえず、個人的にはDB作ってからやるよりは、こんな風にコード書いて勝手にDB作ってくれる方が好みなので、サンプル作るときとかはこれを使おうと思います♪
因みにApp.configに接続文字列を用意すれば、自分で任意のDBを接続先にすることが出来ます。ここらへんの規約やら規約のカスタマイズやらは、勉強しながらBlogにアップできたらと思います。とりあえず今回は手軽にCodeFirstを始める方法だけ書きました。


以上っ!!