事前に生成されたマッピング ビュー

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 ファイルを右クリックします。

ビューの生成

プロセスが完了すると、次のようなクラスが生成されます。

生成されたビュー

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

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

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

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

ビューの生成

ビューを生成する API は、System.Data.Entity.Core.Mapping.StorageMappingItemCollection クラスにあります。 ObjectContext の MetadataWorkspace を使用して、コンテキストの StorageMappingCollection を取得できます。 新しい 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()

最初のメソッドは、コンテナー マッピング内の各ビューのエントリを含むディクショナリを作成します。 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 メソッドによって生成されたディクショナリ内の指定された EntitySetBase に関連付けられた EntitySql を含む DbMappingView を返す必要があります。 EF があなたが持っていないビューを要求した場合、GetView は null を返すべきです。

上で説明したように、Power Tools で生成された DbMappingViewCache からの抽出を次に示します。その中には、EntitySql を格納して取得する 1 つの方法が必要です。

    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");
    }

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

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

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