連載:ADO.NET Entity Framework入門

第2回 EDMにおける多対多関係とEntity Frameworkでのデータの取得/保存

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

Entity Frameworkで自動生成されるクラス

 さて、前回、今回とEDMの概要から少し複雑な機能まで触れることができたので、そろそろアプリケーションからEntity Frameworkを使用する方法について考えたい。まず押さえておきたいのは、EDM保存の際にEntity Frameworkが自動生成する次の2種類のクラスである。

  • エンティティ・クラス
  • オブジェクト・コンテキスト・クラス

 自動生成されたクラスはEDMのファイル名にDesigner.cs(C#の場合)、Designer.vb(VBの場合)を付加した名前で保存されている。今回は図10のようにAddressBook.Designer.cs、AddressBook.Designer.vbとして保存されている。

 なお、これらのファイルは、C#プロジェクトの場合はソリューション・エクスプローラのAddressBook.edmxファイル項目の左側の[+]アイコンをクリックすることで表示できるが、VBプロジェクトの場合はソリューション・エクスプローラの上部の[すべてのファイルを表示]アイコンをクリックする必要がある。


図10 EDMを基に自動生成されたクラス(上がC#、下がVB)
AddressBook.Designer.cs/AddressBook.Designer.vbファイルとして生成される。VBの場合は上部ツールバーにある[すべてのファイルを表示]アイコンをクリックしないと、それらのファイルは表示されない。

 それでは自動生成された2つのクラスについて見ていこう。

■エンティティ・クラス

 エンティティ・クラスとは、EDMで定義したエンティティに対応するクラスである。アプリケーションからEntity Frameworkを使用する際には、このエンティティ・クラスを介してデータのやりとりを行う。

 例えばデータベースのデータはエンティティ・クラスのインスタンスとして取得できる。また、エンティティ・クラスのインスタンスの新規作成やプロパティの変更は、データベースへのレコードの挿入、更新などの操作に対応する。

 Entryエンティティに対応するエンティティ・クラスは、AddressBook.Designer.cs/.vbファイルのEntryクラスとして生成されている(リスト1)。

// Entryクラス
[EdmEntityTypeAttribute(NamespaceName="AddressBook", Name="Entry")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Entry : EntityObject
{
    // IDプロパティ
    [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Int32 ID
    {
      get
      {
        return _ID;
      }
      set

    // Ageプロパティ
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Int16 Age
    {
      get
      {
        return _Age;
      }
      set
      {

    // Categoriesナビゲーション プロパティ
    [XmlIgnoreAttribute()]
    [SoapIgnoreAttribute()]
    [DataMemberAttribute()]
    [EdmRelationshipNavigationPropertyAttribute("AddressBook", "EntryCategory", "Category")]
    public EntityCollection<Category> Categories
    {
      get
      {
' Entryクラス
<EdmEntityTypeAttribute(NamespaceName:="AddressBook", Name:="Entry")>
<Serializable()>
<DataContractAttribute(IsReference:=True)>
Public Partial Class Entry
  Inherits EntityObject

  ' IDプロパティ
  <EdmScalarPropertyAttribute(EntityKeyProperty:=true, IsNullable:=false)>
  <DataMemberAttribute()>
  Public Property ID() As Global.System.Int32
    Get
      Return _ID
    End Get
    Set

  ' Ageプロパティ
  <EdmScalarPropertyAttribute(EntityKeyProperty:=false, IsNullable:=false)>
  <DataMemberAttribute()>
  Public Property Age() As Global.System.Int16
    Get
      Return _Age
    End Get
    Set

  ' Categoriesナビゲーション プロパティ
  <XmlIgnoreAttribute()>
  <SoapIgnoreAttribute()>
  <DataMemberAttribute()>
  <EdmRelationshipNavigationPropertyAttribute("AddressBook", "EntryCategory", "Categories")>
   Public Property Categories() As EntityCollection(Of Category)
    Get
リスト1 Entryエンティティから生成された「Entityクラス」(抜粋)
EDMのプロパティに対応する、C#やVBのプロパティが定義されているのが分かる。

 ここでは、EDMで定義されたID、Ageといったプロパティがそのままソース・コードとして記述されている。また、アソシエーション内でナビゲーション・プロパティとして定義したCategoriesプロパティが、EntityCollectionという、コレクション型のプロパティとして定義されていることにも注目したい。このプロパティにアクセスすることで、エントリに関連付けられたカテゴリ(のコレクション)を取得することができる。

 なお、ここで行ったようにエンティティ・クラスはEntity Frameworkに自動生成させることもできるが、.NET Framework 4からの新機能として、POCO*1をエンティティ・クラスとして使用することもできるようになった。

 上記のサンプル(リスト1)を見れば分かるが、自動生成したエンティティ・クラスはEntityObjectクラスを継承し、さらに各プロパティにはさまざまな属性が必要であり、結果的にEntity Frameworkに深く依存するクラスとなっている。一方、POCOを使用することにより、エンティティ・クラスをフレームワークに依存しないクラスとすることができる。Entity FrameworkにおけるPOCOの利用については、次回以降で扱う予定である。

*1 「Plain-Old CLR Object」の略で、特別なクラスやインターフェイスを継承していないクラスのこと。

■オブジェクト・コンテキスト

 オブジェクト・コンテキストとは、データベースへのコネクションをカプセル化し、データベースからのデータ取得、エンティティ・クラスへの変更をデータベースへ反映させるなどの機能を持つクラスである。Entity Frameworkを使用する際には、ほとんどの場合、このオブジェクト・コンテキスト・クラスのインスタンス作成から、すべての操作が始まるといってよい。

 オブジェクト・コンテキストは、EDM上では「エンティティ・コンテナ」という、エンティティすべてを格納する論理グループとして扱われる(正確には、EDMのエンティティ・コンテナが概念として先にあり、それを実装したものがオブジェクト・コンテキストである)。

 そのため、デフォルトではEDMの名前に「Container」を付加したものがオブジェクト・コンテキスト・クラスの名前として用いられる。

 次のリスト2は、自動生成されたオブジェクト・コンテキスト・クラスのソース・コードの一部である。

  // AddressBookContainer
public partial class AddressBookContainer : ObjectContext
{
  // Entryエンティティの集合に相当するプロパティ
  public ObjectSet<Entry> Entries
  {
    get
    {
       ……中略……
    }
  }

  // Entryエンティティの追加メソッド
  public void AddToEntries(Entry entry)
  {
    base.AddObject("Entries", entry);
  }
' オブジェクト・コンテキスト・クラスAddressBookContainer
Public Partial Class AddressBookContainer
  Inherits ObjectContext

  ' Entryエンティティの集合に相当するプロパティ
  Public ReadOnly Property Entries() As ObjectSet(Of Entry)
    Get
      ……中略……
    End Get
  End Property

  ' Entryエンティティの追加メソッド
  Public Sub AddToEntries(ByVal entry As Entry)
    MyBase.AddObject("Entries", entry)
  End Sub
リスト2 オブジェクト・コンテキスト・クラス(抜粋)

 オブジェクト・コンテキスト・クラスには、各エンティティの集合に相当するプロパティ(Entriesプロパティ)や、新規エンティティを追加するためのメソッド(AddToEntriesメソッド)などが含まれている。特に、エンティティの集合に相当するプロパティは、データのクエリの際に頻繁に使用するので覚えておきたい。


 INDEX
  ADO.NET Entity Framework入門
  第2回 EDMにおける多対多関係とEntity Frameworkでのデータの取得/保存
    1.多対多関係の実現
    2.EDMからデータベースの自動生成
  3.Entity Frameworkで自動生成されるクラス
    4.Entity Frameworkでのデータ保存/取得サンプル
 
インデックス・ページヘ  「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 記事ランキング

本日 月間