我每分钟都在运行一个托管服务。该服务将数据存储在缓存中的表中,然后使用数据并发送邮件。然后它删除记录。我必须这样做,因为如果发送邮件失败,我可以用相同的记录重试。
所以服务从缓存中获取数据。将其存储在表中。它从表中获取数据并发送邮件。成功时,它会从表中删除记录。但是,一分钟后,邮件被第二次发送了。如此接缝,记录不会第一次被删除。
我正在做这样的事情(缩短代码):
// 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();
}
}
}
在同一范围内创建和直接删除数据可能是问题吗?
谢谢!