さまざまな大規模なASP.NET Core MVC 1.0アプリケーションに取り組んでいます。次のように、各アプリケーションに4層があります。
現在、すべてのデータベース操作を処理するリポジトリでは、次のようにDbContextにデータベース接続文字列をハードコーディングしています。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlServer("Data Source=somedatabase.database.windows.net;Initial Catalog=database;Integrated Security=False;User ID=username;Password=password;Connect Timeout=60;Encrypt=True;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true");
}
このプロジェクトは、スタンドアロンASP.NET Core 1.0プロジェクトとしてMVCプロジェクトの外部にあります。また、コードからデータベースへのコマンドラインの実行に必要と思われる空のProgram.csファイルがあります(dotnet ef migrations addおよびdotnet ef database update)。
DbConextにハードコードされた接続文字列がある理由は、次のコードを使用すると、dotnet efコマンドを実行するときに、オブジェクト例外のインスタンスに設定されていないオブジェクト参照を取得するためです。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["StandardDatabase"].ConnectionString);
}
ただし、Program.csがあるため、接続文字列にDebug.WriteLineを追加してプロジェクトを実行すると、正しい接続文字列が返され、UIのappsettings.jsonファイルに接続文字列を設定すると、 UIも正常に接続されます。
問題:上記のスタックは、複数の「マイクロアプリ」に使用するものです。つまり、複数のデータベースに接続する複数のプロジェクトがあります。また、Development、Staging、およびProduction接続文字列を利用したいと考えています。
Configuration Manager接続文字列を使用する場合、すべてが日常の操作に適しています。ただし、Entity Frameworksコードをデータベースコマンドラインに使用する場合は、DbContextをハードコード化された接続文字列に更新および変更する各リポジトリに移動して、コマンドを実行し、完了時に戻す必要があります。 、これは非常に面倒になります。
質問:これは間違っていますか、DbContextを手動で変更しなくても設定ファイルを利用できるようにするEntity Framework Core 1.0スタックを設定するための推奨プラクティスがありますか?ボード?
どんな方向でも大歓迎です!
EF Coreは、依存性注入を介して構成することを目的としています。依存性注入により、DbContextがクリーンに保たれ、環境の実装の詳細に依存しなくなります。
接続文字列をハードコーディングする最初のソリューションは、DbContextをデータベースの場所の情報に密接に結び付けました。それは明らかに問題です。しかし、提案されたソリューションは、DbContextを特定の構成ファイルの知識に密接に結び付けます。それも問題です。
DbContextを環境の詳細に依存しないようにするには、DbContextOptions
パラメーターを取り、基本クラスコンストラクターを呼び出すコンストラクターを作成します。
public class MyContext : DbContext
{
public MyContext(DbContextOptions options) :
base(options)
{
}
}
OnConfiguring
をオーバーライドする代わりにこれを行います。次に、ホストアプリケーションのStartup.cs
で初期化します。ここで、構成ファイルの知識が属します。
public class Startup
{
private IConfigurationRoot _configuration;
public Startup(IHostingEnvironment env)
{
_configuration = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigurationRoot>(_configuration);
services.AddDbContext<MyContext>(options => options
.UseSqlServer(_configuration.GetConnectionString("MyContext")));
}
}
これで、どこからでもDbContextを使用できます。
ANSWER:私はこれを実際よりもずっと難しくしていました。 Juunasのアドバイスに従い、Repository DbContextクラスの次のコードに追加しました。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// get the configuration from the app settings
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
// define the database to use
optionsBuilder.UseSqlServer(config.GetConnectionString("StandardDatabase"));
}
これは、dotnet efコマンドラインツールで完璧に動作し、複数環境のセットアップが、startup.csの次のデフォルトコードを保持するMVC UIで機能する限り、同様にうまく機能します。
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("project.json", optional: true, reloadOnChange: true);
IDbContextFactoryも役立つ場合があります。 EFコマンドラインツールとDIは、このファクトリを使用してDBContextのインスタンスを作成できます。設計時サービス(たとえば、移行)は、派生コンテキストと同じアセンブリにあるこのインターフェイスの実装を検出します。
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace MyProject
{
public class BloggingContextFactory : IDbContextFactory<BloggingContext>
{
public BloggingContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlite("Filename=./blog.db");
return new BloggingContext(optionsBuilder.Options);
}
}
}