次の方法で共有


データ ポイント

Entity Framework 手法の解明: モデル作成ワークフロー

Julie Lerman

Julie LermanMicrosoft Entity Framework はさまざまな開発スタイルのニーズを満たすよう設計されたデータ アクセス テクノロジなので、開発者が選択できるオプションは多数あります。中には、開発サイクル初期に選択する必要があり、その後の開発プロセスで選択するオプションに影響を及ぼすオプションもあります。この 3 回シリーズのコラムでは、Entity Framework で下す必要がある、次のような重要な決定事項についての概要を説明します。

  • 概念モデルを作成する場合の Code First 、Model First、または Database First の各ワークフロー
  • 遅延読み込み、明示的読み込み、または一括読み込み
  • Plain Old C# Object (POCO) または EntityObject
  • LINQ to Entities または Entity SQL

アプリケーション全体では設計に関してもっと多くの決定を下すことになりますが、既存のアプリケーションや新しいアプリケーションへの Entity Framework の実装に着手した開発者からは、上記の決定についての質問が特によく寄せられ、議論の対象になります。

今回のコラムでは、概念モデルを作成する際のワークフローについて取り上げます。他の 3 つのトピックについては、今後 2 回のコラムで取り上げます。繰り返しますが、このシリーズの目的は概要を示すことです。

概念モデルを作成する 3 つのオプション

Entity Framework は、Entity Data Model (EDM) という、ドメイン エンティティの概念モデルを使用します。この EDM の作成方法の選択が、最初に下す必要がある決定です。選択するのは、次の 3 つの独立したワークフローです。

  • Database First ワークフローは、レガシ データベースを出発点とし、ウィザードを利用して、レガシ データベースから概念モデルへのリバース エンジニアリングを行います。
  • Model First ワークフローは、白紙の状態から着手し、ビジュアル EDM デザイナーを使用して EDM を設計し、設計したモデルからデータベース スキーマを生成します。
  • Code First ワークフローは、概念モデルを記述するクラスから開始し、ビジュアル モデルは使用しません。

Database First: レガシ データベースから開始する

この Entity Framework の最初のバージョンでは、先ほど説明したオプションはまったく使用できません。モデルを作成する唯一の方法は、既存のデータベースから EDM にリバース エンジニアリングすることだけです。これを Database First モデリングと呼びます (図 1 参照)。

With Database First, You Reverse-Engineer a Model from a Legacy Database

図 1 Database First ではレガシ データベースからモデルへのリバース エンジニアリングを行う

おそらくこの図を何度もご覧になっていることでしょう。Entity Data Model ウィザードを開き、既存のデータベースを指定し、モデルで表現するテーブル、ビュー、ストアド プロシージャ、およびユーザー定義関数を選択して、[完了] をクリックします。すぐに、モデルが作成されます。Database First モデルの初期状態は、データベース (または選択したデータベースのサブセット) を仮想的に反映したものです。これだけでも、開発者は既に Entity Framework のメリットを得ています。開発者は作成したモデルに対して厳密に型指定したクエリを記述でき、Entity Framework がこのようなクエリを実行して、クエリ結果から厳密に型指定したオブジェクトを具体化します。続いて、開発者が結果を操作するにつれて Entity Framework によってその変更が追跡されるため、SaveChanges コマンドを呼び出すだけで変更をデータベースに保存できます。

モデルの作成だけを Entity Framework に求める開発者もいますが、そのような開発者はモデルを保持する大きなメリットの 1 つを見逃しています。つまり、モデルをデータベースよりもドメイン (アプリケーションを定義するクラスやリレーションシップ) に近づけることができ、そのうえ、データベースに戻す方法を気にする必要がありません (データベースは Entity Framework が管理し続けます)。モデルのカスタマイズは、多くの開発者が見過ごし、メリットを得ていない EDM の重要な機能の 1 つです。カスタマイズでは、モデルへの継承階層の導入、エンティティの整形、エンティティの結合や分割などを実行できます。

Database First では、データベースとモデルの両方のメリットを活かすことができます。つまり、既存のデータベースを活用することでモデルの作成にごく簡単に着手でき、アプリケーション ドメインをより正確に反映するようそのモデルをカスタマイズできます。

Model First: ビジュアル モデルから開始する

出発点となるレガシ データベースが常に存在するとは限りません。このような場合は、Model First により、デザイナーでモデルを直接設計し、設計したモデルに基づいてデータベース スキーマを作成します。デザイナー内で直接、エンティティとそのプロパティを構築し、リレーションシップとその制約を定義し、継承階層を作成します。また、ID キーにするプロパティを指定でき、データベースでキー値を生成する必要がある場合でもこの機能を使用できます (図 2 参照)。

With Model First, You Design a Model that’s Used to Generate Database Schema

図 2 Model First ではデータベース スキーマの生成に使用するモデルを設計する

EDM デザイナーの "モデルからデータベースを生成" 機能は、実際にデータベースを作成するわけではありません。この機能は、実行時にデータベースのスキーマを定義する、SQL を構築します。このような SQL をデータ定義言語 (DDL) と呼びます。

Model First には、明らかにされていない注意点がいくつかあります。Model First は、Visual Studio 2010 および Microsoft .NET Framework 4 で導入されました。そのため Visual Studio 2008 には、[データベースの作成] オプションが表示されません。また、新しい機能なので、使用している ADO.NET データ プロバイダー (System.Data.Sql など) を更新して、この機能が提供されるようにしておく必要があります。Microsoft SQL Server プロバイダーは .NET Framework 4 のリリース時に更新されており、サードパーティ製のプロバイダーの中にも更新されているものがあります。

Model First の既定では、データベースのスキーマを増分更新しないため、対策が必要です。モデルからデータベースを生成する機能を実行すると、すべてのデータベース オブジェクトを削除してから再作成するため、まったく新しい DDL スクリプトが作成されます。外部ツールを使用すると、データベース スキーマを上書きせずに変更できます。外部ツールを使用しないのであれば、データを事前にバックアップしておくか、スクリプトを作成して、モデルを変更する必要が生じるたびにテスト データを再生成し、データベース スキーマを再作成します。

Visual Studio にはデータベース生成の拡張ポイントが用意されているため、マイクロソフトの Entity Designer Database Generation Power Pack を利用できます。これは、Visual Studio 2010 の拡張機能マネージャーまたは visualstudiogallery.com からダウンロードできます。この拡張機能では、Model First でデータベースを増分変更できるだけでなく、既定の Table-Per-Hierarchy 継承マッピングを変更したり、独自のカスタマイズした DDL 生成ルールを作成したりすることもできます。

Code First: コードから開始し物理モデルを使用しない

Database First と Model First では、最終的に EDM の物理表現と追加メタデータを作成することになります。こうしたモデル本来の形式は XML です。メタデータは EDMX という拡張子のファイルに保存されつため、このファイルを EDM デザイナー内で操作するか、手を加えていない XML そのものとして操作します。Entity Framework は実行時にこの XML を読み取り、メタデータ (エンティティ、リレーションシップなど) を表す特殊なクラスを使用して、モデルのメモリ内表現を作成します。Entity Framework ランタイムは、実際の XML ファイルではなく、このオブジェクトを操作します。このメタデータが特に重要になるのは、Entity Framework がモデル クエリをデータベース クエリに変換し、データベースからの結果をエンティティのインスタンスに変換して、データベース コマンド (挿入、更新、および削除) を作成する必要がある場合です。Visual Studio は、アプリケーションで使用するために、XML からドメイン クラスを生成します。

Entity Framework チームは、物理 EDMX ファイルがなくても、必要なメタデータ オブジェクトを実行時に作成できる方法を考案しました。この手法に基づくのが、Code First という Entity Framework の 3 つ目のモデル作成ワークフローです。Code First では、EDM を作成するのではなく、他の .NET 開発と同様にドメイン クラスを作成することになります。実行時に Entity Framework が作成したドメイン クラスを検査し、一連の既定の表記規則を使用して、Entity Framework ランタイムが操作可能なメモリ内モデルを構築します。作成したクラスには Entity Framework がモデルを作成するために必要な情報が常に含まれているとは限らないため、モデルをさらに詳しく記述でき、先ほど述べた既定の表記規則よりも優先される追加構成を (宣言型の属性やデータ注釈を使用するか、コード内で Fluent API を使用して) 提供できます。この追加構成は、Code First の表記規則に従っていない主キーの特定、リレーションシップの調整、さらには継承階層の表現方法の指定など、さまざまな作業に使用できます。

Model First と同様、Code First の既定ではレガシ データベースを出発点としていないことを前提としているため、推測したモデルからデータベースを作成する機能が用意されています。Model First と異なる点は、データベース ファイルとスキーマの両方を作成できることです。Code First にも、モデルを変更してからデータベースを再生成する際にデータベースのデータを保持しておく方法がありません。ただし、Code First ではモデルとデータベースの違いを検出でき、データベースの初期化子を使用してデータをデータベースに入力できます。

Code First は既存のデータベースでも使用できます。クラス名やプロパティ名がデータベースと一致しなければ、Fluent API を使用してデータ注釈や構成を追加することで対処できます。図 3 は、クラスとフィールドが完全には一致しなくても Code First で正しいテーブル名とプロパティ名にマッピングされるようにする属性を指定したクラスを示しています。

図 3 クラスを既存のテーブルに正しくマッピングできるようにする Code First の属性を指定したクラス

[Table("SalesOrderDetail", SchemaName="SalesLT")]
  public partial class Detail
  {
    // Scalar properties

    [Column(Name = "SalesOrderID")]
    public int OrderId { get; set; }
    [Column(Name = "SalesOrderDetailID")]
    public int DetailId { get; set; }
    public short OrderQty { get; set; }
    public int ProductId { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal UnitPriceDiscount { get; set; }

    public decimal LineTotal { get; set; }
    public System.DateTime ModifiedDate { get; set; }

    // Navigation properties

    public virtual Product Product { get; set; }
    public virtual Order Order { get; set; }
  }

デシジョン ツリー

Entity Framework がさまざまな開発スタイルをサポートするまで発展した反面、開発者は適切な手法を選択するために各オプションに精通する必要に迫られています。モデルに UI を使用する場合は、既存のデータベースから開始しても、Model First オプションを使用しても、EDM デザイナーを使用できます。その場合でも、モデル作成ツールを出発点として使用し、テンプレートを使用して Code First のクラスを作成してから、ビジュアル モデルを削除できます。コードこそが重要で、EDMX ファイルやビジュアル モデル作成ツールに縛られないようにする場合は、Code First が適しています (図 4 参照)。

The Decision Tree

図 4 デシジョン ツリー

適切な手法で開始する

Database First、Model First、または Code First のいずれのモデリング手法を選択する場合でも、モデルの作成後は、手法の違いを意識することなく、モデルのクラスと Entity Framework ランタイムを使用してエンティティのクエリ、操作、または保存を開始できます。また、あるワークフローから出発した後、別のワークフローに切り替えることも可能です。DbContext のコード生成テンプレートを使用して、EDMX ファイルから Code First のクラスを作成できます。さらに、それほど簡単ではありませんが、Code First のクラスから EDMX ファイルを作成することもできます。

今回は、各オプションの概要と、あるオプションを他のオプションより優先して選択する基準について説明しました。いくつかのオプションについて皆さんの理解が深まったことを願っています。

今後のコラムでは、今回のコラムの冒頭で示したように、Entity Framework アプリケーションで下す必要がある他の重要な決定事項について説明します。具体的には、コード生成手法としての EntityObject と POCO の選択、一括読み込み、遅延読み込み、または明示的読み込みを使用した関連データの読み込み、および LINQ to Entities または Entity SQL を使用したクエリの作成について説明します。

Julie Lerman は、バーモント ヒルズ在住の Microsoft MVP、.NET の指導者、およびコンサルタントです。世界中のユーザー グループやカンファレンスで、データ アクセスなどの Microsoft .NET トピックについてプレゼンテーションを行っています。彼女のブログは thedatafarm.com/blog (英語) で、彼女が執筆した『Programming Entity Framework』(O'Reilly Media、2010 年) は絶賛を浴びました。Twitter (twitter.com/julielerman、英語) で彼女をフォローしてください。

この記事のレビューに協力してくれた技術スタッフの Tim Laverty に心より感謝いたします。