(標準の依存性注入を使用して)DbContext
インスタンスをIHostedService
にどのように注入する必要がありますか?
現在、コンストラクタでIHostedService
クラスにMainContext
(DbContext
から派生)インスタンスを使用させています。
アプリケーションを実行すると、次の結果が得られます。
シングルトン「Microsoft.Extensions.Hosting.IHostedService」のスコープ付きサービス「Microsoft.EntityFrameworkCore.DbContextOptions」を使用できません。
そこで、以下を指定してDbContextOptions
を一時的にしようとしました。
services.AddDbContext<MainContext>(options =>
options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);
Startup
クラスで。
ただし、 これによりGithubの問題が解決された によると、エラーは同じままです。渡されたDbContextOptions
は、AddDbContext
呼び出しで指定された同じ存続期間を持つ必要があります。
データベースコンテキストをシングルトンにすることはできません。さもないと、データベースコンテキストを同時に呼び出すと、同時実行例外が発生します(データベースコンテキストがスレッドセーフであることが保証されていないため)。
ホストされたサービス内でサービスを使用する良い方法は、必要なときにスコープを作成することです。これにより、サービス/データベースコンテキストなどを、それらがセットアップされているライフタイム構成で使用できます。理論上、スコープを作成しないと、シングルトンDbContextが作成され、不適切なコンテキストが再利用されます(EF Core 2.0 with DbContextプール)。
これを行うには、IServiceScopeFactory
を挿入し、必要に応じてそれを使用してスコープを作成します。次に、このスコープから必要な依存関係を解決します。これにより、ホストされたサービスからロジックを移動し、一部の作業をトリガーするためにのみホストされたサービスを使用する場合、スコープ付きの依存関係としてカスタムサービスを登録することもできますdbコンテキストも挿入されるこのスコープ)。
public class MyHostedService : IHostedService
{
private readonly IServiceScopeFactory scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public void DoWork()
{
using (var scope = scopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
…
}
}
…
}