BackgroundService计时器内的存储过程



我想要一个存储过程,用.net core 3.0运行evrey 5秒。

我一直在使用BackgroundService,当我试图调用存储的proc时,我得到"线程0xcec已退出,代码为">

{
public class ImportScope : BackgroundService
{
private readonly BlockContext _context;
private readonly ILogger<ImportScope> _logger;
private Timer timer;
private readonly IServiceScopeFactory _scopeFactory;
public ImportScope(ILogger<ImportScope> logger, IServiceScopeFactory scopeFactory)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var scope = _scopeFactory.CreateScope();
var blockContext = scope.ServiceProvider.GetRequiredService<BlockContext>();
timer = new Timer(o => blockContext.CourseExtentions.FromSqlRaw("exec stored_proc_wanted")) , null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
}

}

在没有看到Timer实现的情况下,我猜第一个参数是要执行的表达式。首先要考虑的是,DbContexts不是线程安全的,因此它们应该在执行的线程中实例化和处理。

为了可读性,我会创建一个用于执行存储过程的函数,包括DbContext:的作用域

private void execSproc()
{
using (var scope = _scopeFactory.CreateScope())
{
using (var blockContext = scope.ServiceProvider.GetRequiredService<BlockContext>())
{
blockContext.CourseExtentions.FromSqlRaw("exec stored_proc_wanted");
}
}
}

然后在你的定时器任务方法:

protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
timer = new Timer(o => execSproc , null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
return Task.CompletedTask; 
}

这是假设您的Scope正在实现大多数DbContextScope/Unit of Work模式应该实现的IDisposable。最终,DbContext需要在计时器任务上启动的线程中确定作用域。我不确定Task.CompletedTask相对于定时器意味着什么。

我还建议删除:

private readonly BlockContext _context;

因为如果模式要使用ContextScope/UoW(IServiceScopeFactory(,这不是一个注入的成员。这个模式的目的是围绕DbContext提供一个范围,所以你永远不应该挂在对DbContext的引用上。

最新更新