通过依赖注入执行后台任务的DbContext

时间:2016-08-23 19:27:12

标签: dependency-injection asp.net-core asp.net-core-mvc background-process entity-framework-core

我可能没想到正确的方向。我是Dependency Injection和ASP.Net Core的新手。

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

我正在尝试通过以下方式运行后台作业:

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

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

我的问题是,处理这种情况的最佳方法是什么?我应该制作AppDbContext单例吗?我应该在ProcessImport方法中创建一个新的AppDbContext实例,并将其传递给它吗?我读过DbContext不是线程安全的,那么这是一个好方法吗?

2 个答案:

答案 0 :(得分:22)

您应该将IServiceScopeFactory个实例(它的单身人士)传递给您的任务。

在内部任务中,当数据到达时,您应该创建新的CreateScope()并从该范围请求服务。数据处理完成后 - 处理此范围(但保留对IServiceScopeFactory的引用以进行下一次运行)。

例如,请参阅this。我用这个库运行小而快的任务。

对于重型/长时间运行的任务,正如格特写的那样,不要相信你的任务总是会完成。准备好重新启动,准备好重新处理相同的数据。

答案 1 :(得分:4)

分类您的问题:

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

    API处理长时间运行的任务并不理想。您可以将流程委派给后台应用程序

  2. 我应该制作AppDbContext单例吗?

    dbContext不应该是Web应用程序场景中的单例,因为它可能会导致管理事务等问题。

  3. 处理这种情况的最佳方法是什么?

    细分各种服务/流程:

    • 将采用文件的API。理想情况下,API应该只将文件作为输入并将其保存到磁盘或数据库。
    • 将处理文件的服务。将此组件/服务创建为单独的库。然后从控制台应用程序中使用此库。这样您就可以分析性能。通过使其成为异步方法使其成为火并忘记方法。这样您就可以灵活地重用代码。
    • 如果您不希望上传大量文件,可以在API控制器上重用该库,并使用QueueBackgroundWorkItem执行该方法。请参阅此处以供参考:http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
  4. 我应该在ProcessImport方法中创建一个新的AppDbContext实例,然后传递它吗?

    由于它不是线程安全的,因此在每个线程中创建并使用dbContext类的单独实例。

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

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