DbContext通过依赖注入用于后台任务



我想的方向可能不对。我是相当新的依赖注入和ASP。网络核心。

我有ASP。Net core网站,其中一个任务是将数据从excel表格导入到用户将上传的数据库中。excel表格可能很大,数据转换任务很耗时,因此我希望在后台执行它们。即用户将上传表格,响应将立即发送,后台作业/线程将导入数据。

我正在尝试运行后台作业:

Task.Run(() => ProcessImport(model));

我遇到的问题是,Process导入方法调用服务,这些服务具有通过ASP访问AppDbContext的存储库类。Net依赖注入容器,它被添加为作用域,一旦响应被发送回来,上下文就被处理掉。我得到一个运行时异常,你不能使用上下文后,它被处置。

我的问题是,处理这种情况的最好方法是什么?我应该把AppDbContext做成单例吗?我应该在ProcessImport方法中创建AppDbContext的新实例,并将其传递下去吗?我读过DbContext不是线程安全的,所以这是一个好方法吗?

您应该将IServiceScopeFactory实例(它是单例)传递到您的任务中。

在任务内部,当数据到达时,您应该创建新的CreateScope()并从该作用域请求服务。当数据处理结束时,释放这个作用域(但在下次运行时保留对IServiceScopeFactory的引用)。

请看下面的例子。我用这个库运行小而快速的任务。

对于繁重/长时间运行的任务,正如Gert所写的,不要依赖于你的任务总是会运行到完成。准备好重新启动,准备好重新处理相同的数据

分解你的问题:

  1. 处理这种情况的最好方法是什么?

    对于API来说,处理长时间运行的任务并不理想。你可以将进程委托给后台应用程序

  2. 我应该让AppDbContext单例吗?

  3. 在web应用场景中,dbContext不应该是单例的,因为它可能会导致管理事务等问题。
  4. 处理这种情况的最好方法是什么?

    分解各种服务/流程:

    • 将接受文件的API。理想情况下,API应该只接受文件作为输入,并将其持久化到磁盘或数据库。
    • 处理文件的服务。将此组件/服务创建为单独的库。然后从控制台应用程序中使用这个库。这样你就可以分析性能。通过将其设为async方法来实现即发即忘的方法。这样你就可以灵活地重用你的代码。
    • 如果你不期望大量的文件上传,你可以在你的API控制器上重用这个库,并使用QueueBackgroundWorkItem执行这个方法。参考:http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
  5. 我应该在ProcessImport方法中创建AppDbContext的新实例,并将其传递下去吗?

    因为它不是线程安全的,所以在每个线程中创建并使用dbContext类的单独实例

  6. 我读过DbContext不是线程安全的,所以这是一个好方法吗?

    有关使用EF dbContext的深入指南,请查看此博客:http://mehdi.me/ambient-dbcontext-in-ef6/

最新更新