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

Saa*_*ooq 18 dependency-injection background-process entity-framework-core asp.net-core-mvc asp.net-core

我可能没想到正确的方向.我对Dependency Injection和ASP.Net Core相当新.

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

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

Task.Run(() => ProcessImport(model));
Run Code Online (Sandbox Code Playgroud)

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

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

Dmi*_*try 26

您应该将IServiceScopeFactory实例(它的单例)传递给您的任务.

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

例如,见这个.我用这个库运行小而快的任务.

对于重型/长期运行的任务,正如Gert所写,不要依赖于您的任务将始终运行完成.准备好重新启动,准备好重新处理相同的数据.


all*_*tej 5

分解你的问题:

  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/