Я запускаю размещенную службу каждую минуту. Сервис хранит данные в таблице из кеша, затем использует данные и отправляет письмо. Затем он удаляет запись. Я должен это сделать, потому что в случае сбоя отправки почты я могу повторить попытку с той же записью.
Таким образом, служба берет данные из кеша. Хранит в таблице. Он берет данные из таблицы и отправляет почту. В случае успеха он удаляет запись из таблицы. Но через минуту письма были отправлены во второй раз. Похоже, что запись не удаляется с первого раза.
Я делаю что-то вроде этого (сокращенный код):
// 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();
}
}
}
Возможно, проблема заключается в создании и удалении данных в одной и той же области?
Спасибо!