同じ DbContext 型を持つ複数のモデル間で交互に

OnModelCreatingに組み込まれているモデルは、コンテキスト上のプロパティを使用して、モデルの構築方法を変更できます。 たとえば、いくつかのプロパティに基づいてエンティティを異なる方法で構成するとします。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    if (UseIntProperty)
    {
        modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.StringProperty);
    }
    else
    {
        modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.IntProperty);
    }
}

残念ながら、EF はモデルをビルドし、 OnModelCreating を 1 回だけ実行し、パフォーマンス上の理由から結果をキャッシュするため、このコードは as-is機能しません。 ただし、モデル キャッシュ メカニズムにフックして、異なるモデルを生成するプロパティを EF に認識させることができます。

IModelCacheKeyFactory

EF では、 IModelCacheKeyFactory を使用してモデルのキャッシュ キーを生成します。既定では、EF は特定のコンテキスト型に対してモデルが同じであることを前提としているため、このサービスの既定の実装では、コンテキスト型のみを含むキーが返されます。 同じコンテキスト型から異なるモデルを生成するには、 IModelCacheKeyFactory サービスを正しい実装に置き換える必要があります。生成されたキーは、モデルに影響するすべての変数を考慮して、 Equals メソッドを使用して他のモデル キーと比較されます。

次の実装では、モデル キャッシュ キーを生成するときに UseIntProperty が考慮されます。

public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
        => context is DynamicContext dynamicContext
            ? (context.GetType(), dynamicContext.UseIntProperty, designTime)
            : (object)context.GetType();
}

また、デザイン時モデルのキャッシュも処理する Create メソッドのオーバーロードを実装する必要があります。 次の例のように、

public class DynamicModelCacheKeyFactoryDesignTimeSupport : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
        => context is DynamicContext dynamicContext
            ? (context.GetType(), dynamicContext.UseIntProperty, designTime)
            : (object)context.GetType();

    public object Create(DbContext context)
        => Create(context, false);
}

最後に、コンテキストのIModelCacheKeyFactoryに新しいOnConfiguringを登録します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseInMemoryDatabase($"DynamicContext-{UseIntProperty}")
        .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();

詳細なコンテキストについては、 完全なサンプル プロジェクト を参照してください。