質問: ASP.NET Core 1.1でWeb APIを構築しています。 構成、ユーザー、グループ(全体で約25テーブル)などの構成アイテムに共通の基本スキーマを持つ多数の異なるデータベース(異なるシステム用)があります。図に示すように、基本クラスから継承することで、モデルの共有部分の非常に広範なEF構成の重複を避けようとしています。 ![私のDbContext継承ツリー](https://i.stack.imgur.com/mE7SK.jpg) ただし、 `DbContextOptions`をコンストラクターにパラメーターとして渡すというEntity Framework(EF)要件のため、これは機能しません`DerivedRepository`は、コンストラクターが呼び出されるリポジトリーのタイプと一致する必要があります。次に、 `:base(param)`呼び出して、パラメーターをベース`DbContext`渡す必要があります。 したがって、(たとえば)InvestContextが`DbContextOptions`で初期化されると、 `base(DbContextOptions)`が呼び出され、 `ConfigurationContext`コンストラクターの呼び出しが必須ではなく`DbContextOptions`型のパラメーターを受け取るため、EFがエラーをスローします`DbContextOptions`ます。 DbContextのオプションフィールドは次のように定義されているため ``` private readonly DbContextOptions _options; ``` これを回避する方法はわかりません。 共有モデルを一度定義して複数回使用する最良の方法は何ですか?ヘルパー関数を作成し、すべての派生コンテキストから呼び出すことができたと思いますが、継承ほどクリーンまたは透過的ではありません。
回答: これで、上の例のような`InvestContext`を使用して、継承階層を使用する方法でこれを動作させました。 前述のように、InvestContextクラスは`DbContextOptions`型のコンストラクタパラメータを受け取りますが、 `DbContextOptions`をそのベースに渡す必要があります。 私は、 `DbContextOptions`変数からconnectionstringを掘り起こし、必要な型のDbContextOptionsインスタンスを構築するメソッドを作成しました。 InvestContextは、このメソッドを使用して、base()を呼び出す前にoptionsパラメータを正しい型に変換します。 変換方法は次のようになります。 ``` protected static DbContextOptions ChangeOptionsType(DbContextOptions options) where T:DbContext { var sqlExt = options.Extensions.FirstOrDefault(e => e is SqlServerOptionsExtension); if (sqlExt == null) throw (new Exception("Failed to retrieve SQL connection string for base Context")); return new DbContextOptionsBuilder() .UseSqlServer(((SqlServerOptionsExtension)sqlExt).ConnectionString) .Options; } ``` InvestContextのコンストラクタ呼び出しは次のように変更されます。 ``` public InvestContext(DbContextOptions options):base(options) ``` これに: ``` public InvestContext(DbContextOptions options):base(ChangeOptionsType(options)) ``` これまでのところ、InvestContextとConfigurationContextの両方が簡単なクエリで動作しますが、ハックのように思えますし、EF7の設計者が心に留めていたものではないかもしれません。 私はまだ複雑なクエリ、更新などを試みるとEFが結び目になると懸念して*いますが、これは問題ではないようです(下記参照)* **編集:**私はここでEF7チームの問題としてこの問題を記録しました。チームメンバーはEFコアコアの変更を次のように提案しました。 > "TContextを現在のコンテキストタイプから派生した型にするためのチェックを更新する必要があります" > > これは問題を解決するだろう。 そのチームメンバー(これについては問題がわかります)とのやりとりやEFコアコードの掘り下げが行われた後、上記で概説したアプローチは安全であり、提案された変更が実装されるまでは最良のアプローチです。