連載:Entity Framework 4.1入門 第3回 Fluent APIとDbContextの機能 WINGSプロジェクト 土井 毅(監修:山田 祥寛)2011/08/16 |
Page1
Page2
|
EF 4.1連載の最終回となる今回は、「Fluent API」と呼ばれる、エンティティ・クラス外部からデータベースの構造を制御するための機能と、DbContext/DbSetクラスの使用方法について解説する。
■外部からデータベース構造を設定するFluent API
Fluent APIは、コード・ファーストにおいて、デフォルトの規約と異なるモデルを扱う際に使用するAPIである。
前回解説した、エンティティ内に属性として記述する方法(=アノテーション)とは異なり、Fluent APIはエンティティ・クラス外部から設定を行うための仕組みだ(図1)。
図1 アノテーション(上)とFluent API(下)の違い |
Fluent APIを使用する場合、エンティティ・クラス内にEF専用のアノテーションを記述する代わりに、コンテキスト・オブジェクトにデータベースの構造を設定するための記述を行う。エンティティ内にEF用のアノテーションを記述する必要がないため、エンティティをEFに依存させない状態に保つことができる。従って、すでにエンティティ・クラスが存在し、定義に変更を加えたくない場合などに有効である。
一方で、エンティティ・クラス自体を変更して構わない場合は、アノテーションによる記述の方が直感的で記述しやすい。Fluent APIは手続き的、アノテーションによる定義は宣言的、とも言い換えられるだろう。それぞれのプロジェクトにあった方法を選択してほしい。
●Fluent APIの使用方法
それではCompositeKeyEntityエンティティ(図2)を例に、Fluent APIの使用方法について解説していく。
図2 CompositeKeyEntityエンティティ |
CompositeKeyEntityエンティティはKey1、Key2という2つのプロパティを複合キーとして持つエンティティである。クラス定義はリスト1のようになる。
|
||
リスト1 CompositeKeyEntityエンティティのクラス定義(上:CompositeKeyEntity.cs、下:CompositeKeyEntity.vb) |
このクラス定義には、複合キーやフィールド名を設定するためのアノテーション(=前回解説したKey属性やColumn属性)が含まれていないため、このままでは主キーを特定できず、モデル・エラーが発生する。また、備考プロパティのフィールド名もそのまま「備考」となってしまう。そこで、Fluent APIを使い、Key1/Key2プロパティを複合キーに、備考プロパティのフィールド名を「Memo」に設定してみよう。
Fluent APIは、モデル構築時に呼び出される、(コンテキスト・オブジェクトのイベント・ハンドラである)OnModelCreatingメソッド内から使用する。
OnModelCreatingメソッドの引数は、エンティティ・クラスとデータベース定義のマッピングを設定するためのDbModelBuilderクラス(System.Data.Entity名前空間)のオブジェクトである。Fluent APIは、このDbModelBuilderオブジェクトを起点とし、メソッドを連ねて(流れるように)呼び出していくことに特徴がある*1。
*1 こうしたメソッドを連ねていく手法のことを「Fluent Interface(流れるようなインターフェイス)」と呼ぶこともある。JavaScriptライブラリのjQueryなどがその代表例。 |
リスト2は、CompositeKeyEntityエンティティについて、複合の主キーKey1/Key2と、「備考」プロパティのデータベース上のフィールド名を「Memo」に設定するコードである。
|
||
リスト2 Fluent APIによる設定例(上:ItemCatalog.cs、下:ItemCatalog.vb) |
アノテーションの代わりに、メソッドの連なりでデータベースの設定を行っている点に注目してほしい。このコードは、図3のように、起点となるDbModelBuilderオブジェクトから、複数のメソッドが流れるようにして実行される。
図3 メソッドが流れるように連なっていく |
以上のようにOnModelCreatingメソッドでデータベースの構造を設定すれば、エンティティ・クラスを使用するコードはアノテーションで定義した場合とまったく同じものを使用可能である。
●Fluent APIの構造
以降は、理解を深めるためFluent APIの構造について解説する。
Fluent APIは、メソッドを連続して呼び出すことができるよう、各メソッドが返すオブジェクトに特徴がある。
図4 DbModelBuilderオブジェクトからのメソッドによる遷移 |
起点となるDbModelBuilderオブジェクトからは、図4のように、EntityメソッドやComplexTypeメソッドを呼び出すことで、エンティティと複合型の設定を行うためのEntityTypeConfigurationオブジェクトやComplexTypeConfigurationオブジェクトを取得できる。
図5 EntityTypeConfigurationオブジェクトからのメソッドによる遷移 |
エンティティの設定を行うEntityTypeConfigurationオブジェクトからは、図5のように、プロパティの設定を行うためのPropertyメソッドによってXXXPropertyConfiguration(XXXの部分はプロパティのデータ型に応じて変化)オブジェクトを取得できる。
例えば、文字列のプロパティについてはStringPropertyConfigurationオブジェクトが、日時型のプロパティについてはDateTimePropertyConfigurationオブジェクトが、Propertyメソッドの戻り値として返る。先ほどのCompositeKeyEntityエンティティの例では、備考プロパティに対応するStringPropertyConfigurationオブジェクトが返されていた。
XXXPropertyConfigurationオブジェクトには、アノテーションで設定するのと同じような、フィールド名やデータ型の設定を行うメソッドが準備されている。先ほどの例では、フィールド名を設定するためのHasColumnNameメソッドを使用した。
同様に、リレーションの設定を行うためのHasMany/HasRequired/HasOptionalメソッドにより、XXXNavigationPropertyConfiguration(XXXの部分はリレーションの種類に応じて変化)オブジェクトを取得できる。
こうした仕様により、メソッドを連ねてのモデル構築を行える。表1は、Fluent APIで使用できる主要なメソッドである。
クラス | メソッド | 意味 | 戻り値の型 |
DbModelBuilder | Entity | エンティティの設定 | EntityTypeConfiguration |
ComplexType | 複合型の設定 | ComplexTypeConfiguration | |
Ignore | クラスをデータベースと連動させない | DbModelBuilder | |
EntityTypeConfiguration | HasKey | 主キーの設定 | EntityTypeConfiguration |
HasMany | リレーションシップの設定(多) | ManyNavigationPropertyConfiguration | |
HasRequired | リレーションシップの設定(一。必須) | RequiredNavigationPropertyConfiguration | |
HasOptional | リレーションシップの設定(一。オプショナル) | OptionalNavigationPropertyConfiguration | |
EntityTypeConfiguration, ComplexTypeConfiguration | Property | プロパティの設定 | XXXPropertyConfiguration (XXXはプロパティの型に合わせた名前) |
Ignore | プロパティをデータベースと連動させない | ||
XXXPropertyConfiguration | IsRequired | 必須設定(SQLのNOT NULL) | XXXPropertyConfiguration (自分自身のオブジェクト) |
IsOptional | オプショナル設定 | ||
HasColumnName | フィールド名の設定 | ||
HasColumnType | データ型の設定 | ||
HasMaxLength | 最大長の設定(文字列型の場合) | ||
XXXNavigationPropertyConfiguration | WithMany | リレーションシップの参照側の設定(多) | DependentNavigationPropertyConfiguration |
WithRequired | リレーションシップの参照側の設定(一。必須) | ForeignKeyNavigationPropertyConfiguration | |
WithOptionalDependent | リレーションシップの参照側の設定(一。オプショナル) | ||
DependentNavigationPropertyConfiguration | HasForeignKey | 外部キーの設定 | CascadableNavigationPropertyConfiguration |
表1 Fluent APIの主要なメソッド |
なお、DbModelBuilder/EntityTypeConfiguration/ComplexTypeConfigurationオブジェクトのIgnoreメソッドは、NotMappedアノテーションに相当するもので、指定したエンティティやプロパティをデータベースと関連付けない、という設定を行うためのメソッドである。
●Fluent APIの設定例
Fluent APIは多数のメソッドやクラスを用意しているため、すべてを紹介することはできない。詳細については、MSDNの「DbModelBuilderオブジェクトのページ」を起点に確認してほしい。また、Visual StudioのIntelliSenseはFluent APIと相性がよく、慣れれば自然にメソッドを連ねて記述できるだろう。
参考までに、リスト3にFluent APIによるいくつかの設定例を示す。ここでは、1対多関係のリレーションシップや多対多関係のリレーションシップをFluent APIを使って記述している。
|
||
リスト3 Fluent APIによるリレーションの設定例(上:ItemCatalog.cs、下:ItemCatalog.vb) |
これらのコードにより、ItemとMemberの1対多リレーションシップについては図6のように、ItemとCategoryの多対多リレーションシップについては図7のようなデータベース構造となる。
図6 ItemとMemberの1対多リレーションシップ |
図 7ItemとCategoryの多対多リレーションシップ |
INDEX | ||
[連載]Entity Framework 4.1によるコード・ファースト開発 | ||
第3回 Fluent APIとDbContextの機能 | ||
1.外部からデータベース構造を設定するFluent API | ||
2.DbContext、DbSetクラスの使用方法 | ||
「連載:Entity Framework 4.1入門」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|