我想要一个存储过程,用.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的引用上。