【问题标题】:How to inject repository in .net core 3.1 background service?如何在 .net core 3.1 后台服务中注入存储库?
【发布时间】:2020-08-01 20:21:13
【问题描述】:

在 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>();

存储库:

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);
        }
    }
}

后台服务:

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);
}

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

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

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

任何帮助将不胜感激。

【问题讨论】:

    标签: c# .net-core entity-framework-core


    【解决方案1】:

    AddDbContextDbContext 注册为范围服务。所以你只能在一个范围内解析该服务。

    因此,您只需创建一个范围并在不再需要时将其丢弃:

    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);
            }
        }
    }
    
    

    【讨论】:

      【解决方案2】:

      默认情况下,后台服务没有创建范围。要解析 DbContext 等作用域服务,您需要在根容器之外创建一个子作用域。

      看看how to use scoped services in background services

      【讨论】:

        猜你喜欢
        • 2020-08-21
        • 2018-01-23
        • 2021-09-11
        • 2023-03-31
        • 2022-01-07
        • 1970-01-01
        • 1970-01-01
        • 2012-08-26
        • 2021-09-28
        相关资源
        最近更新 更多