У меня есть следующий интерфейс
internal interface IScopedProcessingService
{
Task DoWork(CancellationToken stoppingToken);
}
и реализация
public class ConsumeScopedServiceHostedService : BackgroundService
{
private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
public ConsumeScopedServiceHostedService(IServiceProvider services,
ILogger<ConsumeScopedServiceHostedService> logger)
{
Services = services;
_logger = logger;
}
public IServiceProvider Services { get; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service running.");
await DoWork(stoppingToken);
}
private async Task DoWork(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service is working.");
using (var scope = Services.CreateScope())
{
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWork(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service is stopping.");
await Task.CompletedTask;
}
}
Этот код взят из официальной документации Microsoft. Фоновые сервисы с областями действия
И, как в документации, у меня есть ScopedProcessingService
, но несколько сложнее. Вот код:
internal class ScopedProcessingService : IScopedProcessingService
{
private int _executionCount;
private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
private readonly IPushRepository _pushRepository;
private readonly IPushTemplateRepository _pushTemplateRepository;
private readonly ISenderLogRepository _senderLogRepository;
private readonly IDistributionRepository _distributionRepository;
// services
private readonly IPushTemplateService _pushTemplateService;
private readonly ISendPushService _sendPushService;
public ScopedProcessingService(
ILogger<ConsumeScopedServiceHostedService> logger,
IPushTemplateService pushTemplateService, ISendPushService sendPushService,
IPushRepository pushRepository,
ISenderLogRepository senderLogRepository, IDistributionRepository distributionRepository,
IPushTemplateRepository pushTemplateRepository)
{
_logger = logger;
_pushTemplateService = pushTemplateService;
_sendPushService = sendPushService;
_pushRepository = pushRepository;
_senderLogRepository = senderLogRepository;
_distributionRepository = distributionRepository;
_pushTemplateRepository = pushTemplateRepository;
}
public async Task DoWork(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_executionCount = _senderLogRepository.SenderLogs.Count();
var logMessage = new StringBuilder();
logMessage.AppendLine($"Начинаю рассылку № {_executionCount}.");
// get all templates. THIS CALL IS A SOURCE OF PROBLEMS
var templates = _pushTemplateRepository.PushTemplates.Where(x => x.isActive)
.Include(x => x.Messages)
.ThenInclude(x => x.PushLang)
.Include(x => x.Category)
.Include(x => x.AdvertiserPushTemplates)
.ThenInclude(x => x.Advertiser)
.ToList();
}
}
В классе Startup.cs
я использую следующий код для его внедрения:
services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<IScopedProcessingService, ScopedProcessingService>();
Проблема с этой строкой var templates = _pushTemplateRepository.PushTemplates.Where(x => x.isActive)
. Если я внесу некоторые изменения с PushTemplate
, эти изменения не будут действовать в фоновом режиме. И я буду обрабатывать старые данные. Я имею в виду, если я изменю имя для PushTemplate
, например, с id = 15 с Name_1
на Name_2
, чем у меня будет Name_1
в фоновой задаче.
Как добавить EF
в фоновом сервисе Scoped правильно? Я не использую четкий контекст EF. У меня есть слой хранилища.
public interface IPushTemplateRepository
{
IQueryable<PushTemplate> PushTemplates { get; }
void Save(PushTemplate pushTemplate);
void Delete(int templateid);
}
И реализация
public class PushTemplateRepository : IPushTemplateRepository
{
private readonly ApplicationDbContext _applicationContext;
public PushTemplateRepository(ApplicationDbContext applicationContext)
{
_applicationContext = applicationContext;
}
public IQueryable<PushTemplate> PushTemplates => _applicationContext.PushTemplates;
public void Save(PushTemplate pushTemplate)
{
// ...
}
public void Delete(int templateid)
{
// ...
}
}