如何在.net core 3.1后台服务中注入存储库?

Meh*_*hdi 2 c# entity-framework-core .net-core

在asp.net core 3.1 Web应用程序中,我有一个从BackgroundService类继承的事件监听器。为什么注入了DbContext的injectiong存储库会出错?

启动:

    services.AddDbContext<DBContext>(options => {
        options.UseSqlServer("...connection string...");
    });

    services.AddTransient<ICalStatRepo, CalStatRepo>();
    services.AddTransient<IHostedService, BackgroundListener>();
Run Code Online (Sandbox Code Playgroud)

存储库:

public class CalStatRepo : ICalStatRepo
{
    private readonly DBContext _context;

    public CalStatRepo(DBContext context)
    {
        _context = context;
    }

    public async Task InsertCallStat(RawCallStatRegisterViewModel model)
    {
        var rawCall = new RawCallStat
        {
            HappenedAt = model.HappenedAt,
            Source = model.Source,
            Destination = model.Destination,
            Status = model.Status
        };

        _context.Entry(rawCall).State = EntityState.Added;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (Exception e)
        {
            throw new Exception("Insert new call stat fails with this error : " + e.Message);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

后台服务:

public class BackgroundListener : BackgroundService
{
    private readonly IServiceProvider _service;

    public BackgroundListener(IServiceProvider service)
    {
        _service = service;
    }
}
// what I want to do is insert logs into db here
private async void EvenetListener(Object sender, Event e)
{
    var calStatRepo = _service.GetRequiredService<ICalStatRepo>(); //> Error

    await calStatRepo.InsertCallStat(args);
}
Run Code Online (Sandbox Code Playgroud)

问题是在事件监听器中添加所需的服务会出现如下错误:

无法从根提供程序解析“Repositories.ICalStatRepo”,因为它需要范围服务“Models.Context.DBContext”。

DBContext 在启动时添加为 services.AddDbContext 并注入到 CalStatRepo 中,然后在后台服务的事件侦听器中添加为所需服务,但为什么又需要将其作为作用域服务呢?

任何帮助将不胜感激。

Sir*_*ufo 8

AddDbContext将 注册DbContext为范围服务。所以你只能在一个范围内解决该服务。

因此,您只需创建一个作用域并在不再需要时将其处置:

public class BackgroundListener : BackgroundService
{
    private readonly IServiceProvider _service;

    public BackgroundListener(IServiceProvider service)
    {
        _service = service;
    }

    // what I want to do is insert logs into db here
    private async void EvenetListener(Object sender, Event e)
    {
        using ( var scope = _service.CreateScope() )
        {
            var calStatRepo = scope.ServiceProvider.GetRequiredService<ICalStatRepo>();
            await calStatRepo.InsertCallStat(args);
        }
    }
}

Run Code Online (Sandbox Code Playgroud)