ygo*_*goe 7 dependency-injection asp.net-core asp.net-core-2.1
因此,ASP.NET Core应用程序内置了“依赖关系注入”。借助Entity Framework Core,您可以轻松地从控制器操作方法中获取具有范围的DbContext实例。
但这仅限于控制器动作。如果您需要从某个动作开始长时间运行的后台任务,该动作将通过WebSocket之类的其他方式与浏览器中的视图进行通信,那么您突然一无所有。后台任务无法使用操作的DbContext,因为该操作已在操作返回时进行了范围划分和处置。
一种简单的方法是使用人们所谓的服务定位器。这是某些IServiceProvider的静态副本,用于以后的访问和服务解析。(ASP.NET Core 2.1可能需要使用与我在此注释中阅读的方法不同的方法。)但是,无论我看什么,都将其描述为反模式。它使测试更加困难并且混淆了依赖性。好的。
那么对于这种情况推荐的解决方案是什么?我在茫茫荒野中的某个地方。甚至可以从调度程序而不是控制器操作启动的后台任务。附近没有HTTP请求。DI在这里可以为我做什么?有没有不退后于反模式的解决方案?我确定ASP.NET Core DI的创建者已经想到了这一点。
是否有办法使服务在那里解决,或更改我的体系结构以使后台任务本身以某种方式脱离DI?
更新:通过评论请求,例如:控制器动作启动某件事。就像网络扫描一样,这将需要很长时间。该视图返回类似“尊敬的用户,请稍等,您可以观看此进度条”。工作在后台继续,不断将进度和/或结果发布到浏览器。(浏览器也可能会轮询进度。)后台任务需要访问数据库以存储扫描结果。扫描完成后,浏览器可以通过另一个操作来获取它。因此,如果后台任务仅使用控制器动作的DbContext,则在动作完成后将变得不可用。
另一个示例是与请求完全无关的后台服务。定期检查数据库然后执行某些操作的服务。这也需要一个DbContext,甚至无处尝试窃取它。
在这种情况下,您只能依靠作为反模式的servicelocater模式。同样,DbContext必须是每个实例独立的(瞬态),而不是作用域。
我的建议是注入IServiceScopeFactory一个单例,然后开始在后台工作中执行任务的范围。
using (var scope = _serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<DbContext>();
// now do your work
}
Run Code Online (Sandbox Code Playgroud)
没有别的了。这些东西不是mvc管道的一部分,因此无法即时解决。我也建议不要在某个地方直接访问dbcontext。将内容包装在存储库中,然后使用该存储库,甚至将该存储库包装在所谓的服务类中。因此,您的逻辑被封装了,您的后台工作人员仅在收到消息时执行事情。
没有直接关系,但是ASP.NET-Core具有IHostedService内置的后台工作器。
编辑:正如史蒂文(Steven)在下面建议的那样,当手动解析/启动类时,它可能并不总是反模式。至少当compositionroot照顾它时,不是这样。这是他提供的链接,解释得很好。
| 归档时间: |
|
| 查看次数: |
2044 次 |
| 最近记录: |