如何在 .NET Web 中使用 BackgroundService 中的数据库 API

How to use the database from a BackgroundService in .NET Web API

我正在构建一个微服务,它应该通过各种方式发送定期通知。

为了处理通知和触发器,我打算使用一个 BackgroundService,它将查看数据库,根据通知类型调用适当的服务,并将通知标记到数据库中作为已发送。

如何以安全的方式从后台服务访问数据库,而不会出现并发问题?

注入 IServiceProvider 并创建作用域是否足够?

public class MyBackgroundService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public MyBackgroundService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await DoWorkAsync(stoppingToken);
    }

    private async Task DoWorkAsync(CancellationToken stoppingToken)
    {

        using (IServiceScope scope = _serviceProvider.CreateScope())
        {
            IRepository<Notification> notificationRepository =
                scope.ServiceProvider.GetRequiredService<IRepository<Notification>>();
            IRepository<NotificationLog> notificationLogRepository =
                scope.ServiceProvider.GetRequiredService<IRepository<NotificationLog>>();
            IUnitOfWork unitOfWork = 
                scope.ServiceProvider.GetRequiredService<IUnitOfWork>();

                
            while(true)
            {
                 if(stoppingToken.IsCancellationRequested)
                 {
                     return;
                 }

                var list = await notificationRepository.GetAll();
                .....................................
                await notificationLogRepository.Add(...);
                await unitOfWork.Commit();
            }
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {

        await base.StopAsync(stoppingToken);
    }
}

Is it enough to inject IServiceProvider and create a scope?

是的。

虽然您可以为整个后台工作人员的生命周期创建一个范围,但您也可以为每个“调用”创建一个范围 - 在这种情况下,您可以创建一个新范围每次定时器响起。这样,如果出现下一个调用在当前调用完成之前开始的情况,将保证这两个调用具有不同的范围。

但是,如果您的“计时器”只是在执行 await Task.Delay,那么就不可能出现重叠调用,并且不需要单独的范围。无论如何,有些人更喜欢它们,因为“调用”和“范围”在概念上可以很好地结合在一起。