コードベースの構成
Note
EF6 以降のみ - このページで説明する機能、API などは、Entity Framework 6 で導入されました。 以前のバージョンを使用している場合、一部またはすべての情報は適用されません。
Entity Framework アプリケーションの構成は、構成ファイル (app.config または web.config) またはコードで指定できます。 後者は、コードベースの構成と呼ばれています。
構成ファイルでの構成については、別の記事で説明しています。 構成ファイルは、コードベースの構成よりも優先されます。 つまり、コードと構成ファイルの両方で構成オプションが設定されている場合、構成ファイルの設定が使用されます。
DbConfiguration
の使用
EF6 以降でコードベースの構成を行うには、System.Data.Entity.Config.DbConfiguration
のサブクラスを作成します。 DbConfiguration
のサブクラスを作成する際は、次のガイドラインに従う必要があります。
- アプリケーションに使用する
DbConfiguration
クラスを 1 つだけ作成します。 アプリ ドメイン全体の設定をこのクラスで指定します。 DbContext
クラスと同じアセンブリにDbConfiguration
クラスを配置します。 (これを変更したい場合は、「DbConfiguration
を移動する」セクションを参照してください。)DbConfiguration
クラスに、パラメーターなしのパブリック コンストラクターを記述します。- このコンストラクター内から protected
DbConfiguration
メソッドを呼び出して構成オプションを設定します。
これらのガイドラインに従うことで、モデルにアクセスする必要のあるツールによって、また、アプリケーションの実行時に、必要な構成を EF が自動的に検出して使用できるようになります。
例
以下に示したのは、DbConfiguration
から派生したクラスの例です。
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;
namespace MyNamespace
{
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb"));
}
}
}
このクラスは、失敗したデータベース操作を自動的に再試行する SQL Azure 実行戦略を使用し、Code First から規約により作成されるデータベースにローカル DB を使用するように EF を設定します。
DbConfiguration
を移動する
DbContext
クラスと同じアセンブリに DbConfiguration
クラスを配置できないケースもあります。 たとえば、2 つの DbContext
クラスがそれぞれ異なるアセンブリに存在する場合があります。 この場合、2 つの対処法があります。
1 つ目は、使用する DbConfiguration
インスタンスを構成ファイルで指定する方法です。 そのためには、entityFramework セクションの codeConfigurationType 属性を設定します。 次に例を示します。
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
...Your EF config...
</entityFramework>
codeConfigurationType の値には、DbConfiguration
クラスのアセンブリと名前空間の修飾名を指定する必要があります。
2 つ目は、DbConfigurationTypeAttribute
をコンテキスト クラスで設定する方法です。 次に例を示します。
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
この属性の値には、DbConfiguration
型 (上記) を渡すか、またはアセンブリと名前空間の修飾型名文字列を渡すことができます。 次に例を示します。
[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}
DbConfiguration
を明示的に設定する
いくつかの状況では、DbContext
型が使用される前に構成が必要となる場合があります。 この例には以下のようなものがあります。
DbModelBuilder
を使用して、コンテキストなしでモデルを作成する- その他、
DbContext
を利用するなんらかのフレームワークまたはユーティリティ コードを使用する際、そのコンテキストが、自分のアプリケーションのコンテキストよりも前に使用される
このような状況では EF が構成を自動的に検出できないため、次のいずれかの操作を手動で行う必要があります。
- 構成ファイルで
DbConfiguration
型を設定する (前出の「DbConfiguration
を移動する」セクションを参照) - アプリケーションの起動中に
DbConfiguration
.SetConfiguration 静的メソッドを呼び出す
DbConfiguration
をオーバーライドする
いくつかの状況では、DbConfiguration
で設定された構成をオーバーライドする必要があります。 通常、これを行うのはアプリケーション開発者ではなく、派生 DbConfiguration
クラスを使用できないプラグインやサード パーティのプロバイダーです。
この目的のために、EntityFramework では、イベント ハンドラーを登録して、既存の構成がロック ダウンされる前に、それを変更できるようになっています。 EF サービス ロケーターから返されたサービスを置き換えることに特化した便利なメソッドも用意されています。 次のような使い方が意図されています。
- アプリの起動時 (EF が使用される前) に、プラグインまたはプロバイダーは、このイベントのイベント ハンドラー メソッドを登録する必要があります。 (この処理は、アプリケーションによって EF が使用される前に行う必要があります。)
- 置き換えを必要とする各サービスについて、イベント ハンドラーが ReplaceService を呼び出します。
たとえば、IDbConnectionFactory
と DbProviderService
を置き換えたければ、このようなハンドラーを登録することになります。
DbConfiguration.Loaded += (_, a) =>
{
a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s));
a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s));
};
上記のコードでは、MyProviderServices
と MyConnectionFactory
が実際のサービスの実装を表します。
さらに依存関係のハンドラーを追加して、同様の効果を実現することもできます。
この方法で DbProviderFactory
をラップすることもできますが、その作用が及ぶのは EF のみであり、EF の外部における DbProviderFactory
の使用には作用しないことに注意してください。 このような理由から、おそらく DbProviderFactory
は今後も、以前と同じようにラップすることになるでしょう。
また、パッケージ マネージャー コンソールから移行を実行する場合など、アプリケーションの外部で実行するサービスにも注意を払う必要があります。 コンソールから移行を実行すると、DbConfiguration
の検索が試みられます。 しかしサービスがラップされるかどうかは、イベント ハンドラーがどこで登録されるかによって異なります。 DbConfiguration
が構築される過程で登録されれば、コードが実行され、サービスはラップされます。 通常、そのようなケースに該当することはなく、そうなると当然、サービスはラップされません。
.NET