連載:ADO.NET Entity Framework入門

第6回 EF4によるN層アーキテクチャと自己追跡エンティティ【前編】

WINGSプロジェクト 土井 毅 著/山田 祥寛 監修
2010/12/03
Page1 Page2 Page3

■自己追跡エンティティの実装を確認

 それでは、自動生成された自己追跡エンティティの実装を見てみよう。リスト1はEntry.cs/Entry.vbファイルで定義されたEntryエンティティの実装である。

// WCF用の属性
[DataContract(IsReference = true)]
[KnownType(typeof(Category))]
// 2つのインターフェイスを実装(後述)
public partial class Entry: IObjectWithChangeTracker, INotifyPropertyChanged
{
  // エンティティのプロパティ
  [DataMember]
  public string Name
  {
    // 読み取りはそのまま
    get { return _name; }

    // 書き込みの際に、値が変わっていたら
    // OnPropertyChangedメソッドを呼び出す
    set
    {
      if (_name != value)
      {
        _name = value;
        OnPropertyChanged("Name");
      }
    }
  }

  // 変更履歴管理オブジェクト(ChangeTracker)を更新
  protected virtual void OnPropertyChanged(String propertyName)
  {
    if (ChangeTracker.State != ObjectState.Added
          && ChangeTracker.State != ObjectState.Deleted)
    {
      // 状態が追加・削除でなければ、状態を変更(Modified)に
      ChangeTracker.State = ObjectState.Modified;
    }
    if (_propertyChanged != null)
    {
      _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  // 変更履歴管理オブジェクト
  private ObjectChangeTracker _changeTracker;

  ……

' WCF用の属性
<DataContract(IsReference:=True)>
<KnownType(GetType(Category))>
' 2つのインターフェイスを実装(後述)
Partial Public Class Entry
  Implements IObjectWithChangeTracker
  Implements INotifyPropertyChanged

  ' エンティティのプロパティ
  <DataMember()>
  Public Property Name() As String

    '読み取りはそのまま
    Get
      Return _name
    End Get

    ' 書き込みの際に、値が変わっていたら
    ' OnPropertyChangedメソッドを呼び出す
    Set(ByVal value As String)
      If Not Equals(_name, value) Then
        _name = value
        OnPropertyChanged("Name")
      End If
    End Set
  End Property

  ' 変更履歴管理オブジェクト(ChangeTracker)を更新
  Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
    If ChangeTracker.State <> ObjectState.Added AndAlso ChangeTracker.State <> ObjectState.Deleted Then
      ' 状態が追加・削除でなければ、状態を変更(Modified)に
      ChangeTracker.State = ObjectState.Modified
    End If
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
  End Sub

  ' 変更履歴管理オブジェクト
  Private _changeTracker As ObjectChangeTracker

  ……

リスト1 自動生成された自己追跡エンティティの実装内容(Entry.cs/Entry.vb)

 まず気付くのは、いくつかの属性と、クラスが実装しているインターフェイスである。正直、最初にこれを見たときは「これは本当にPOCOなのか?」と疑問に思うかもしれない。しかし、ここで使用されている属性やインターフェイスは、Entity Framework依存のものではなく、.NET Framework汎用のものである。以下にまとめておこう。

 クラスやプロパティに付加されたDataContract/KnownType/DataMember属性(リスト1− )はいずれもWCFでエンティティを公開する際に必要な属性である。自己追跡エンティティはWCFで公開するケースがほとんどと思われるため、これは自然な実装である。

 IObjectWithChangeTrackerインターフェイスは自己追跡機能を持つオブジェクトであることを表すインターフェイスであり、自己追跡エンティティと同時に自動生成されたファイル(AddressBookModelSelfTracking.cs/AddressBookModelSelfTracking.vb)で定義されている。INotifyPropertyChangedインターフェイスは、プロパティの変更をクライアントに伝えるための.NET標準のインターフェイスである。ユーザー・インターフェイスで、データをコントロールにバインドする際に使用されるものである。

 このように、一見するとPOCOに見えないコードではあるが、それぞれは.NET標準であったり、自分で定義したものであったりするため、自己追跡エンティティはEntity Frameworkには依存しておらず、Entity FrameworkをサポートしていないSilverlightでもそのまま使用することができる。

 注目したいのはエンティティのプロパティ(リスト1− )で、読み取りは通常どおりカプセル化されたフィールドを返すだけだが、書き込みの際に、値が変わっていたらOnPropertyChangedメソッドを呼び出す、という処理が加わっている。

 呼び出されたOnPropertyChangedメソッド(リスト1− )では、追加/削除されたエンティティでなければ、状態を変更(Modified)に更新している。

 なお、リスト1− で変更履歴管理を行うObjectChangeTrackerクラスは、ヘルパー・クラスとして自己追跡エンティティと同時に自動生成されている。定義は長いので省略するが、特に重要な、エンティティの状態を表すStateプロパティの列挙型はリスト2のように値が定義されている。

[Flags]
// エンティティの状態を表す列挙型
public enum ObjectState
{
  Unchanged = 0x1, // 変更なし
  Added     = 0x2, // 追加
  Modified  = 0x4, // 変更
  Deleted   = 0x8  // 削除
}
' エンティティの状態を表す列挙型
Public Enum ObjectState
  Unchanged = &H1 ' 変更なし
  Added     = &H2 ' 追加
  Modified  = &H4 ' 変更
  Deleted   = &H8 ' 削除
End Enum
リスト2 エンティティの状態を表すObjectState列挙型
(SelfTrackingEntityModel1.cs/SelfTrackingEntityModel1.vb)

 このように、シンプルなPOCOによるエンティティ・クラス実装に、変更履歴を管理するための機構を追加することで、エンティティに加えられた変更を自分で管理(=自己追跡)することが可能となっている。

【コラム】自己追跡エンティティはPOCO?

 最初に触れたとおり、自己追跡エンティティの実装は直感的にPOCOとは思えないかもしれない。POCOというと、継承や属性を行わない、シンプルなクラスである、という認識があるためだ。

 自己追跡エンティティで使用する各種属性やインターフェイスは自分で定義するものもあるが、主にWCFで使用するDataContract属性なども含まれている。ただ、そうした属性やインターフェイスは、.NET標準でサポートされているものであり、それを使っても依然として「Plainである(=特定のフレームワークに依存していない)」という主張は受け入れられるものだろう。

 また、Entity FrameworkをサポートしていないSilverlightでも読み込めることからも、自己追跡エンティティは広い意味でPOCOと呼べるだろう。

まとめ

 今回はEntity Frameworkを使用した3層アーキテクチャの解説から、自己追跡エンティティの概要と実装までを確認することができた。

 次回はWCFによるサービスの公開と、クライアントを実装し、自己追跡エンティティを使うことで、どのように変更履歴が管理されるかを見ていこう。End of Article

 

 INDEX
  ADO.NET Entity Framework入門
  第6回 EF4によるN層アーキテクチャと自己追跡エンティティ【前編】
    1..NETでの3層アーキテクチャ/変更履歴管理とは/自己追跡エンティティとは
    2.自己追跡エンティティを使った3層アーキテクチャ・サンプル
  3.自己追跡エンティティの実装を確認/【コラム】自己追跡エンティティはPOCO?
 
インデックス・ページヘ  「ADO.NET Entity Framework入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間