web-dev-qa-db-ja.com

DbContextインスタンスをIHostedServiceに挿入するにはどうすればよいですか?

質問

(標準の依存性注入を使用して)DbContextインスタンスをIHostedServiceにどのように注入する必要がありますか?

私が試したもの

現在、コンストラクタでIHostedServiceクラスにMainContextDbContextから派生)インスタンスを使用させています。

アプリケーションを実行すると、次の結果が得られます。

シングルトン「Microsoft.Extensions.Hosting.IHostedService」のスコープ付きサービス「Microsoft.EntityFrameworkCore.DbContextOptions」を使用できません。

そこで、以下を指定してDbContextOptionsを一時的にしようとしました。

services.AddDbContext<MainContext>(options => 
                options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);

Startupクラスで。

ただし、 これによりGithubの問題が解決された によると、エラーは同じままです。渡されたDbContextOptionsは、AddDbContext呼び出しで指定された同じ存続期間を持つ必要があります。

データベースコンテキストをシングルトンにすることはできません。さもないと、データベースコンテキストを同時に呼び出すと、同時実行例外が発生します(データベースコンテキストがスレッドセーフであることが保証されていないため)。

28
Shoe

ホストされたサービス内でサービスを使用する良い方法は、必要なときにスコープを作成することです。これにより、サービス/データベースコンテキストなどを、それらがセットアップされているライフタイム構成で使用できます。理論上、スコープを作成しないと、シングルトン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>();
            …
        }
    }
    …
}
63
Martin Ullrich