読者です 読者をやめる 読者になる 読者になる

EntityFrameworkって何?

EntityFramework ASP.NET MVC

仕事でEntityFrameworkを使うかもしれないので、今のところの知識をまとめてみました。

EntityFrameworkとは?

Ruby on RailsにおけるActiveRecord .NETバージョン。O/Rマッパー。

ActiveRecordに相当するのは、POCOエンティティ(Plain Old CLR Object)という、プロパティだけを持つクラスです。ただ、これはRailsActiveRecordのように自動生成されずユーザーが自作します。

public class Student
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
}

こんな感じのエンティティをModelフォルダ内に作ります。

そしてこのデータをDBから読み込むためにSystem.Data.Entity.DbContextを継承したコンテキストクラスを作ります。

// DbContext を継承する必要がある
public class MyContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Teacher> Teachers { get; set; }
}

プロジェクトをビルドしたタイミングで、コンテキストクラスと同名のデータベースが、そのDB内にPOCOエンティティと同名のテーブルが、自動生成されます。
DBのテーブルにアクセスする際は、このコンテキストクラスのプロパティを使います。

DBからデータを読み込むには↓のようにします。

using (var context = new MyDbContext())
{
   var student = context.Students.Find(x => x.Name == "Yuichi"); //Find()のタイミングでクエリ発行
   var students = context.Students.Where(x => x.Age <= 20).ToArray(); //ToArray()のタイミグでクエリ発行

    //...
}

usingを使っているのは、コンテキストクラスを確実にDisposeするためです。 また、上記2クエリはFindメソッドが実行されるタイミング、ToArrayメソッドが実行されるタイミングでそれぞれ、DBに対してクエリが発行されています。 ですので、クエリが発行されるタイミングを意識して、使用時には不要なDBアクセスを極力抑えるように注意する必要があります。

データの追加、更新、削除は↓のようにやります。

    using (var context = new MyDbContext())
    {
   // 追加
        // Addした段階ではSql文はDBに発行されない
        context.Students.Add(new Student
        {
            Name = "Daisuke",
            Age = 18,
        });

        //更新
   var student = context.Students.Find(x => x.Name == "Yuichi"); //Find()のタイミングでクエリ発行
        student.Age = 26;

        //削除
        var deleteTarget = context.Students.Find(x => x.Name == "Takashi");
        context.Students.Remove(deleteTarget);

        // SaveChangesが呼び出された段階で初めてInsert,Update,Delete文が発行されます
        context.SaveChanges();
    }

通常は、更新、削除処理はDBContext経由で読みだした(Find、Whereで読み込んだ)データに対してのみ行なえます。 しかし、例えば削除対象のデータの主キーが予めわかっている場合は、そのデータを事前に読み込むのは冗長な気がします。 そんなときは、Attachメソッドを使います。

    using (var context = new MyDbContext())
    {
   //削除(削除対象のIDが予めわかっている時)
        var deleteTarget = new Student { Id = 1 };
        context.Students.Attach(deleteTarget);
        context.Students.Remove(deleteTarget);
        
        context.SaveChanges();
    }

データベースファーストについて

この記事で紹介したのは、まずPOCOエンティティを作って、それに合わせて自動的にDBが作成される、いわゆるコードファーストという手法です。 (EntityFramework自体はこのコードファーストという手法をAsp.NET MVCで実現する為に考案されたものです) しかし、既にデータベースが存在している場合は、既存のテーブルからPOCOエンティティを作成する必要があります。 これをデータベースファースといいます。 これについては、また記事を分けてまとめていきたいと思います。