Teched 2009 フォローアップ2 【T2- 309 ADO.NET Entity Framework and LINQ データアクセス開発】

お疲れさまです。昨晩は気温が低く仕事も一段落したこともありグッスリ眠れました。9時間くらい寝ましたね。私、6時間くらいは睡眠時間が必要な人間です。みなさんはいかがでしょうか?以前、どこかで見かけた調査結果によると日本人は平均的に睡眠時間がかなり少ないようです(たしか6時間くらい)。例えばオーストラリアは平均8時間睡眠のようです。8時間毎日はちょっと長い気がしますね。個人的には短時間睡眠で活動的な人が羨ましいです。数年前、慣れれば短時間睡眠でも生活可能だと考え、一週間ほど4時間睡眠にチャレンジしました。。。。。。。結果、仕事どころではありませんでしたね。

今日はTech・Ed 2009【T2- 309 ADO.NET Entity Framework and LINQ データアクセス開発】のフォローアップです。このセッションでは以下の3点について解説しました。

・概念モデリング

・パフォーマンスチューニング

・例外処理(‘楽観的同時実行処理)

1. デモ環境の準備

デモで使用した環境は以下の通りです。

・Windows 7 RTM

・Visual Studio 2008 SP1

・SQL Server 2008 Express Edition

・データベース

School サンプル データベースの作成 (Entity Framework クイック スタート)

http://msdn.microsoft.com/ja-jp/library/bb399731.aspx

2. 概念モデリング

概念モデリングについては下記のチュートリアルをご確認ください。セッションと略、同じ内容です。

http://msdn.microsoft.com/ja-jp/library/cc716693.aspx

3. パフォーマンスチューニング

下記4点ついて、解説しました。

・View Generation

http://msdn.microsoft.com/ja-jp/library/bb896240.aspx

・NoTrackingオプション

http://msdn.microsoft.com/ja-jp/library/system.data.objects.mergeoption.aspx

デモでは下記のように定義しました。

  db.Course.MergeOption = MergeOption.NoTracking;

  db.Course.Where(c => c.Department.Name.Contains("工学部")).ToList();

・Compiled Query

http://msdn.microsoft.com/ja-jp/library/system.data.objects.compiledquery.aspx

 デモではDelegate関数を下記のように定義しました。

  public static Func<SchoolEntities1, IQueryable<Person>>

      compiledPerson = CompiledQuery.Compile(

                                      (SchoolEntities1 db) =>

                                          (from p in db.Person.Include("Course")

                                           orderby p.Name

  where p.OfficeAssignment.Location == "小田急サザンタワー キャンパス"

                                           select p)

                                      );

・Foreign Key

http://msdn.microsoft.com/ja-jp/library/dd283138(VS.100).aspx

※ Visual Studio 2010ではFKもスカラプロパティとして値を取得可能になります。

- 参照系

デモでは下記のようにしてFKを取得しました。

var courseGrade = db.CourseGrade;

  foreach (var cg in courseGrade)

      {

      int enrollmentid = cg.EnrollmentID;

          Decimal? grade = cg.Grade;

          int personid = (int)cg.PersonReference.EntityKey.EntityKeyValues.First().Value;

          int couseid = (int)cg.CourseReference.EntityKey.EntityKeyValues.First().Value;

}

- 更新系

デモでは下記のようにしてFKをセットしました。

cg.PersonReference.EntityKey = new System.Data.EntityKey("SchoolEntities.Person", "PersonID", personid[i % 10]);

      cg.CourseReference.EntityKey = new System.Data.EntityKey("SchoolEntities.Course", "CourseID", courseid[i % 10]);

   db.SaveChanges();

4. 例外処理(楽観的同時実行処理)

http://msdn.microsoft.com/ja-jp/library/bb738618.aspx

- 管理者画面のエラーハンドリング

            try

            {

                db.SaveChanges();

            }

            catch (OptimisticConcurrencyException ex)

            {

                StringBuilder msg = new StringBuilder();

                // 更新衝突が発生した エンティティ を取得

            foreach (var se in ex.StateEntries)

                {

                    foreach (var ek in se.EntityKey.EntityKeyValues)

                    {

                        msg.Append("key:" + ek.Key + " ");

                        msg.Append("value:" + ek.Value + " ");

                    }

                }

                MessageBox.Show("更新衝突が発生しました:" + msg.ToString());

                // 楽観同時制御を無視トラッキングデータをリフレッシュ

                db.Refresh(RefreshMode.ClientWins, db.CourseGrade);

               db.SaveChanges();

            }

- 一般ユーザー画面のエラーハンドリング

            try

            {

                db.SaveChanges();

            }

            catch (OptimisticConcurrencyException ex)

            {

                StringBuilder msg = new StringBuilder();

                // 更新衝突が発生した エンティティ を取得

                foreach (var se in ex.StateEntries)

                {

                    foreach (var ek in se.EntityKey.EntityKeyValues)

                    {

                        msg.Append("key:" + ek.Key + " ");

                        msg.Append("value:" + ek.Value + " ");

                    }

                }

                MessageBox.Show("更新衝突が発生しました:" + msg.ToString());

                // DB の最新データでトラッキングデータをリフレッシュ

                db.Refresh(RefreshMode.StoreWins, db.CourseGrade);

            }