Entity Framework 4.1のCode First

正式リリースと言うことで、ウォークスルーを見ながら書いてみました。

作り方はコンソールアプリケーションのプロジェクトを作り、次の二つの参照を追加します。

  1. System.ComponentModel.DataAnnotations
  2. EntityFramework

EntityFramworkのアセンブリは間違えずにVersion 4.1の物を選択してください。

次のようにコードを追加します。

基本的にはDbContextを継承して作るコンテキストオブジェクトとその設定を行うDatabaseクラスが実務的なコーディングでは重要になりそうなので、そのあたりを重点的に学習した方が良さそうです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.ComponentModel.DataAnnotations;

namespace EF1
{
    //Logクラスの定義
    public class Log
    {
        //主キーの属性
        [Key]
        public int LogId { get; set; }
        public DateTime time { get; set; }
        public string description { get; set; }
        //こうしておくとリレーションが設定される
        public virtual Machine Machine { get; set; }
    }
    //Machineクラスの定義
    public class Machine
    {
        //主キーの属性
        [Key]
        public int MachineId { get; set; }
        public string name { get; set; }
        //こうしておくとリレーションが設定される。こちらの主キーがLogの外部キーに設定される。
        public virtual ICollection Logs { get; set; }
    }

    //コンテキストオブジェクト
    public class LogContext : DbContext
    {
        public DbSet Logs { get; set; }
        public DbSet Machines { get; set; }
    }

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

            //コードでスキーマ変更が行われた場合に変更をDBに反映する。
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges());

            using (var context = new LogContext()) {
                //必要ならばMachineの更新をする。
                Machine Alis;
                Machine Ellen;
                var alis = context.Machines.LongCount(e => e.name == "Alis");
                if (alis == 0) {
                    Alis = new Machine { name = "Alis" };
                    context.Machines.Add(Alis);
                }
                else {
                    Alis = context.Machines.Where(e => e.name == "Alis").First();
                }
                var ellen = context.Machines.LongCount(e => e.name == "Ellen");
                if (ellen == 0) {
                    Ellen = new Machine { name = "Ellen" };
                    context.Machines.Add(Ellen);
                }
                else {
                    Ellen = context.Machines.Where(e => e.name == "Ellen").First();
                }
                int recordsAffected = context.SaveChanges();

                Console.WriteLine("Saved {0} entities to the database.", recordsAffected);
                //Linq式でクエリーもできる。
                var allAlis = from p in context.Machines
                              where p.name == "Alis"
                              orderby p.name
                              select p;

                foreach (var mac in allAlis) {
                    Console.WriteLine(" - {0}", mac.name);
                }
                //Logの追加
                Console.WriteLine("** Create Log Data **");
                int i = 0;

                for (i = 0; i < 10; i++) {
                    if ((i % 2) == 0) {
                        context.Logs.Add(new Log { Machine = Alis, 
                            time = DateTime.Now, 
                            description = "Description : " + i.ToString() });
                    }
                    else {
                        context.Logs.Add(new Log { Machine = Ellen, 
                            time = DateTime.Now, 
                            description = "Description : " + i.ToString() });
                    }
                }

                context.SaveChanges();
                //追加したLogの表示
                foreach (var log in context.Logs) {
                    Console.WriteLine("{0:yyyy/MM/dd hh:mm:ss.fff} : {1}\t: {2}", 
                        log.time, log.Machine.name, log.description);
                }

                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
            }

        }
    }

}

データはApp.ConfigでしてしなければデフォルトではSQL Serverの.\SQLEXPRESSインスタンスにEF内の命名規則に合わせたデータベース名(<プロジェクト名>.<DbContextを継承したクラスの名前>)でデータベースが作成され、その中にデータクラスのクラス名でテーブルが作成されます。(テーブル名はコード内で属性で指定できます。)

既存データベースを使いたかったり、規定の命名規則ではないデータベース名にしたい場合にはApp.ConfigにconnectionStringを書きます。

追記:
プロファイラで見ると結構やばいSQLをEFが吐いているような感じがします。データ件数やトランザクション増えたときに大丈夫かな。。。手動でSQL文チューニングする方法もなさそうな感じが。

4 thoughts on “Entity Framework 4.1のCode First”

  1. ピンバック: .NET Clips
  2. ピンバック: OPC Diary

コメントを残す