【问题标题】:Stored Procedure inside a BackgroundService TimerBackgroundService 计时器内的存储过程
【发布时间】:2021-03-22 15:23:40
【问题描述】:

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

我一直在使用 BackgroundService,当我尝试调用存储过程时,我得到“线程 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;
    }
}

}

【问题讨论】:

    标签: entity-framework stored-procedures .net-core background-service


    【解决方案1】:

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

    为了便于阅读,我会创建一个函数来执行存储过程,包括 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 正在实现 IDisposable ,大多数 DbContextScope / Unit of Work 模式应该是。最终,DbContext 需要在定时器任务上启动的线程内限定范围。我不确定Task.CompletedTask 与计时器的关系是什么。

    我还建议删除:

    private readonly BlockContext _context;
    

    因为如果模式要使用 ContextScope / UoW (IServiceScopeFactory),这不是注入成员。此模式的目的是提供围绕 DbContext 的范围,因此您永远不应该挂在引用上到 DbContext。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-01
      • 2012-11-19
      • 1970-01-01
      • 2013-11-16
      • 1970-01-01
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多