Tech・days 2010 デモのフォローアップ 5 Self Tracking Entities 編【T2-305 ADO.NET Entity Framework】


さて、今日は最後のテーマになります。 Self-Tracking Entities です。

これは N 層アプリケーションが前提となる機能でした。

N層についての細かい話はここで書くよりも、非常に良い記事がMSDNに掲載されています。

まずはリソース情報をご覧ください。

 

リソース情報

・n 層アプリケーションで回避すべきアンチパターン
   http://msdn.microsoft.com/ja-jp/magazine/dd882522.aspx

・n 層アプリケーションのパターン
   http://msdn.microsoft.com/ja-jp/magazine/ee321569.aspx

・EF4 による n 層アプリケーションの構築
   http://msdn.microsoft.com/ja-jp/magazine/ee335715.aspx

 

 

実装方法

細かい実装方法については過去の記事を参考にしてください。

   http://blogs.msdn.com/daisukei/archive/2009/11/20/ado-net-entity-framework-n.aspx

 

 

インストール

・Visual Studio 2010 Beta 2をご利用の方はここからexeをダウンロードしてインストールしてください。尚、日本語版では動作しません。

・Visual Studio 2010 RC をご利用の方はインストールは必要ありません。そのまま利用できます。

 

 

デモ

Tech Days では下記のように Client と Server の2層シナリオで検証してみました。

Entities プロジェクトには 生成した Self Tracking Entities を含めます。

キャプチャ

 

 

最終的にはこんな感じになります。

ここに行き着くまでの細かい手順は以前のポストを参考にしてください。

キャプチャ

 

 

サービス側の実装は次のようにしました。(デモ用なので細かいところは適当です。すみません。)

ApplyChanges 一発でまとめて Entity を更新できるのが非常に便利ですね。以前は、Insert、Update、Delete毎にインタフェースを分けたり、更新前後2つのEntityを取得するインタフェースを実装して対応していましたね。また Person – CourseGrade のように階層構造を持つエンティティを意識した実装も困難でした。

ちなみにOptimisticConcurrencyException は楽観的同時実行のエラーです。

public class Service1 : IService1
{
    public Person GetPerson(int id)
    {
        Person result;
        using (schooldbEntities db = new schooldbEntities())
        {
            result = (from p in db.People.Include("CourseGrades")
                      where p.PersonId == id
                      select p).First();
        }
        return result;
    }

    public Boolean UpdatePerson(Person p)
    {
        Boolean result = true;

        using (schooldbEntities db = new schooldbEntities())
        {
            try
            {
                db.People.ApplyChanges<Person>(p);
                db.SaveChanges();
            }
            catch (OptimisticConcurrencyException ex)
            {
                result = false;
            }
        }
        return result;
    }
}

 

 

クライアント側のコードは次のようにしました。

こちらも UpdatePerson 一発でまとめて処理できるのは非常に便利ですね。

var sv = new ServiceReference1.Service1Client();
// Person エンティティ取得
Person p = sv.GetPerson(2);
Console.WriteLine(p.Name);
foreach (var cg in p.CourseGrades)
{
    Console.WriteLine(cg.CourseName + ":" + cg.Grade);
}

// 最初は楽観的同時実行制御のテストを行う
p.Name = "小高 太郎_update";

// CourseGrade エンティティを削除、更新
CourseGrade cg_syakai = p.CourseGrades.Where(cg => cg.CourseName.Equals("社会")).First();
cg_syakai.MarkAsDeleted();
CourseGrade cg_rika = p.CourseGrades.Where(cg => cg.CourseName.Equals("理科")).First();
cg_rika.CourseName = "生活";

// CourseGrade エンティティの追加
CourseGrade cg_eigo = new CourseGrade();
cg_eigo.CourseName = "英語";
cg_eigo.Grade = 0;
cg_eigo.Person = p;
cg_eigo.CourseGradeId = 100;
p.CourseGrades.Add(cg_eigo);

sv.UpdatePerson(p);

// 更新後の値チェック
Person p_new = sv.GetPerson(2);
Console.WriteLine("更新後のデータ");
Console.WriteLine(p_new.Name);
foreach (var cg in p_new.CourseGrades)
{
    Console.WriteLine(cg.CourseName + ":" + cg.Grade);
}

 

以上でフォローアップは終了です。ありがとうございました。


Comments (0)

Skip to main content