Share via


事前生成済みマッピング ビュー

Entity Framework は、データ ソースに対してクエリを実行したり変更内容を保存したりする前に、データベースにアクセスするための一連のマッピング ビューを生成する必要があります。 マッピング ビューはデータベースを抽象的に表す Entity SQL ステートメントであり、アプリケーション ドメインごとにキャッシュされるメタデータの一部でもあります。 同じアプリケーション ドメインに同じコンテキストの複数のインスタンスを作成した場合、それらのインスタンスはマッピング ビューを再生成するのではなく、キャッシュされたメタデータからそれらを再利用します。 マッピング ビューの生成は、初回クエリ実行に伴うコスト全体の中で大きな割合を占めているため、Entity Framework は、マッピング ビューを事前に生成し、コンパイルされたプロジェクトにそれらを追加できるようになっています。 詳細については、パフォーマンスに関する考慮事項 (Entity Framework) を参照してください。

EF Power Tools Community Edition を使用してマッピング ビューを生成する

ビューを事前生成する方法としては、EF Power Tools Community Edition を使用するのが最も簡単です。 Power Tools をインストールすると、[ビューの生成] というメニュー オプションが表示されます (下図)。

  • Code First のモデルの場合、目的の DbContext クラスがあるコード ファイルを右クリックします。
  • EF Designer のモデルの場合、EDMX ファイルを右クリックします。

generate Views

この処理が完了すると、次のようなクラスが生成されます。

generated Views

以後アプリケーションを実行すると、EF が必要に応じてこのクラスを使用してビューを読み込みます。 モデルが変更されているにもかかわらず、このクラスを再生成しなかった場合は、EF から例外がスローされます。

コードからマッピング ビューを生成する - EF6 以降

ビューを生成するもう 1 つの方法は、EF が提供する API を使用する方法です。 この方法を使用するとビューを自由にシリアル化できますが、ビューの読み込みも自分で行う必要があります。

Note

EF6 以降のみ - このセクションで取り上げる API は Entity Framework 6 で導入されました。 以前のバージョンを使用している場合、この情報は当てはまりません。

ビューの生成

ビューを生成するための API は System.Data.Entity.Core.Mapping.StorageMappingItemCollection クラスにあります。 コンテキストの StorageMappingCollection は、ObjectContext の MetadataWorkspace を使用して取得できます。 より新しい DbContext API を使用している場合は、次のように IObjectContextAdapter を使用してこれにアクセスできます。このコードでは、そこから派生した DbContext のインスタンス (dbContext) を用意しています。

    var objectContext = ((IObjectContextAdapter) dbContext).ObjectContext;
    var  mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace
                                                                        .GetItemCollection(DataSpace.CSSpace);

StorageMappingItemCollection を取得すると、GenerateViews メソッドと ComputeMappingHashValue メソッドにアクセスできるようになります。

    public Dictionary<EntitySetBase, DbMappingView> GenerateViews(IList<EdmSchemaError> errors)
    public string ComputeMappingHashValue()

1 つ目のメソッドでは、コンテナー マッピングの各ビューのエントリを含んだディクショナリを作成しています。 2 つ目のメソッドは単一のコンテナー マッピングのハッシュ値を計算するもので、ビューが事前生成されて以来、モデルが変更されていないことを確認する目的で実行時に使用されます。 2 つのメソッドには、複数のコンテナー マッピングが関係する複雑なシナリオに対応するためのオーバーライドが用意されています。

ビューを生成するときは、GenerateViews メソッドを呼び出し、その結果得られた EntitySetBase と DbMappingView を書き出します。 さらに、ComputeMappingHashValue メソッドによって生成されたハッシュを格納する必要があります。

ビューを読み込む

GenerateViews メソッドによって生成されたビューを読み込むためには、DbMappingViewCache 抽象クラスを継承するクラスを EF に与えます。 DbMappingViewCache には、開発者が実装すべき 2 つのメソッドが規定されています。

    public abstract string MappingHashValue { get; }
    public abstract DbMappingView GetView(EntitySetBase extent);

MappingHashValue プロパティは、ComputeMappingHashValue メソッドによって生成されたハッシュを返す必要があります。 EF は、ビューを要求するときに、まずモデルのハッシュ値を生成して、このプロパティから返されたハッシュと比較します。 両者が一致しない場合は、EF から EntityCommandCompilationException 例外がスローされます。

GetView メソッドは EntitySetBase を受け取り、GenerateViews メソッドによって生成されたディクショナリから、生成された EntitySql を含み、指定された EntitySetBase に関連付けられている DbMappingVIew を返す必要があります。 GetView は、存在しないビューが EF から要求された場合、null を返す必要があります。

次のコードは、前述の Power Tools を使用して生成された DbMappingViewCache から抜粋したものです。必要な EntitySql を格納したり取得したりする方法が確認できます。

    public override string MappingHashValue
    {
        get { return "a0b843f03dd29abee99789e190a6fb70ce8e93dc97945d437d9a58fb8e2afd2e"; }
    }

    public override DbMappingView GetView(EntitySetBase extent)
    {
        if (extent == null)
        {
            throw new ArgumentNullException("extent");
        }

        var extentName = extent.EntityContainer.Name + "." + extent.Name;

        if (extentName == "BlogContext.Blogs")
        {
            return GetView2();
        }

        if (extentName == "BlogContext.Posts")
        {
            return GetView3();
        }

        return null;
    }

    private static DbMappingView GetView2()
    {
        return new DbMappingView(@"
            SELECT VALUE -- Constructing Blogs
            [BlogApp.Models.Blog](T1.Blog_BlogId, T1.Blog_Test, T1.Blog_title, T1.Blog_Active, T1.Blog_SomeDecimal)
            FROM (
            SELECT
                T.BlogId AS Blog_BlogId,
                T.Test AS Blog_Test,
                T.title AS Blog_title,
                T.Active AS Blog_Active,
                T.SomeDecimal AS Blog_SomeDecimal,
                True AS _from0
            FROM CodeFirstDatabase.Blog AS T
            ) AS T1");
    }

追加した DbMappingViewCache を EF に使用させるには、DbMappingViewCacheTypeAttribute を使用し、それが作成されたコンテキストを指定します。 次のコードでは、MyMappingViewCache クラスに BlogContext を関連付けています。

    [assembly: DbMappingViewCacheType(typeof(BlogContext), typeof(MyMappingViewCache))]

もっと複雑なシナリオでは、マッピング ビュー キャッシュ ファクトリを指定することで、マッピング ビュー キャッシュ インスタンスを用意することができます。 そのためには、抽象クラス System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory を実装します。 使用されるマッピング ビュー キャッシュ ファクトリのインスタンスは、StorageMappingItemCollection.MappingViewCacheFactoryproperty を使用して取得または設定できます。