.netcore3 / EF / HostedService: данные удаляются только при втором запуске - PullRequest
1 голос
/ 30 мая 2020

Я запускаю размещенную службу каждую минуту. Сервис хранит данные в таблице из кеша, затем использует данные и отправляет письмо. Затем он удаляет запись. Я должен это сделать, потому что в случае сбоя отправки почты я могу повторить попытку с той же записью.

Таким образом, служба берет данные из кеша. Хранит в таблице. Он берет данные из таблицы и отправляет почту. В случае успеха он удаляет запись из таблицы. Но через минуту письма были отправлены во второй раз. Похоже, что запись не удаляется с первого раза.

Я делаю что-то вроде этого (сокращенный код):

// my hostedservice class
public Task StartAsync(CancellationToken cancellationToken)
{
     // start timer
     _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(_timeout));
     return Task.CompletedTask;
}

private void DoWork(object state)
{
     using var scope = _serviceScopeFactory.CreateScope();
     ICacheService cacheService = scope.ServiceProvider.GetService<ICacheService>();
     IMailService mailService = scope.ServiceProvider.GetService<IMailService>();
     // transfer mails from cache
     for(...) {
          mailRepo.CreateMail(tmpMails[i]).GetAwaiter().GetResult();
          // cache gets cleared successfully, transfer is done only one time
     }
     // send mails
     List<Mail> mails = mailRepo.GetMailsForSend().GetAwaiter().GetResult();
     for(...) {
          // send mail
          // this one seems to work only on second time
          mailRepo.DeleteMail(mail).GetAwaiter().GetResult();
     }
}
// mailRepo
public async Task<bool> CreateMail(Mail mail)
{
     Add(mail);
     await _context.SaveChangesAsync();
     return true;
}
public async Task<bool> DeleteMail(Mail mail)
{
     Delete(mail);
     await _context.SaveChangesAsync();
     return true;
}
public async Task<List<Mail>> GetMailsForSend()
{
     return await _context.Set<Mail>().Where(m => m.NextTry<=DateTime.Now).ToListAsync();
}
// base functions, just for completion
public virtual void Add(T entity)
        {
            EntityEntry dbEntityEntry = _context.Entry<T>(entity);
            _context.Set<T>().Add(entity);
        }
public virtual void Delete(T entity)
        {
            EntityEntry dbEntityEntry = _context.Entry<T>(entity);
            dbEntityEntry.State = EntityState.Deleted;
        }

Пожалуйста, дайте мне подсказку, как я могу улучшите мой код или в чем может быть причина.

Обновление 02.06.2020

Я обнаружил, что все работает как ожидалось при использовании разделенных областей.

private void DoWork(object state)
{
     using(var scope = _serviceScopeFactory.CreateScope()) {
        ICacheService cacheService = scope.ServiceProvider.GetService<ICacheService>();
        IMailService mailService = scope.ServiceProvider.GetService<IMailService>();
        // transfer mails from cache
        for(...) {
            mailRepo.CreateMail(tmpMails[i]).GetAwaiter().GetResult();
            // cache gets cleared successfully, transfer is done only one time
        }
     }
     using(var scope = _serviceScopeFactory.CreateScope()) {
        IMailService mailService = scope.ServiceProvider.GetService<IMailService>();
         // send mails
         List<Mail> mails = mailRepo.GetMailsForSend().GetAwaiter().GetResult();
         for(...) {
              // send mail
              // gets deleted on first run now
              mailRepo.DeleteMail(mail).GetAwaiter().GetResult();
         }
    }
}

Возможно, проблема заключается в создании и удалении данных в одной и той же области?

Спасибо!

...