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

DbContext for background tasks via Dependency Injection

我可能没有在正确的方向思考。我对依赖注入和 ASP.Net Core 还很陌生。

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

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

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

我 运行 遇到的问题是 Process 导入方法调用具有存储库 类 的服务,通过 ASP.Net 添加为 Scoped 的依赖注入容器访问 AppDbContext,一旦响应被发回,上下文被处理掉。我收到一个 运行 时间异常,您无法在处理上下文后使用它。

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

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

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

例如,参见 this。我 运行 使用此库执行小而快的任务。

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

分解您的问题:

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

    API 处理长运行 任务并不理想。您可以将进程委托给后台应用程序

  2. 我应该创建 AppDbContext 单例吗?

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

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

    细分各种services/process:

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

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

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

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