c# - 无法在启动配置时从委托访问 DI 服务?
问题描述
我正在尝试使用委托方法 OnGenerateSitemaps 向食人鱼站点地图添加一些项目。
在这个方法中,我调用了一个从实体框架上下文中获取数据然后缓存它的服务。每当我尝试在委托方法中使用此服务时,我都会收到一个错误,即 dbContext 已被释放。
System.AggregateException: '发生一个或多个错误。(无法访问已释放的上下文实例。此错误的常见原因是释放从依赖注入解析的上下文实例,然后尝试在应用程序的其他地方使用相同的上下文实例。如果您调用“Dispose”,则可能会发生这种情况在上下文实例上,或者将其包装在 using 语句中。如果您使用依赖注入,则应该让依赖注入容器负责处理上下文实例。
我尝试过使服务同步而不是异步,我尝试过等待结果并运行任务同步,但这些都不起作用。
关于如何在启动时配置中的此委托中使用我的服务的任何想法?
services.AddScoped<ICachedSitemapService, CachedSitemapService>();
在启动时,我注入了服务,它是作用域的。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApi api, ICachedSitemapService cachedSitemapService)
{
App.Hooks.OnGenerateSitemap += (sitemap) =>
{
var items = await cachedSitemapService.GetCachedClinics().Result;
sitemap.AddRange(items);
return sitemap;
};
}
调用的服务是 DbContext 来获取项目:
private async Task<IEnumerable<SitemapItem>> GetSitemapClinics()
{
var spec = new ClinicSitemapSpecification();
//This throws error
var allClinics = await _clinicRepo.ListAsync(spec);
//code shortened for brevity, but returns a list.
}
我在下面尝试过没有任何运气。
var items = await cachedSitemapService.GetCachedClinics().GetAwaiter().GetResult();
sitemap.AddRange(items);
解决方案
我们(Piranha 团队)计划重新设计版本 10 中的钩子系统(必须是主要版本,因为它会破坏向后兼容性)以在所有钩子中提供 DI 功能。但是,与此同时,以下内容应该可以解决您的问题。
using (var scope = app.ApplicationServices.CreateScope())
{
var service = scope.ServiceProvider.GetService< ICachedSitemapService>();
}
由于您的服务已注册为范围,因此无法直接从根提供程序解析(如错误状态)。从控制器解析服务时,您处于请求范围内,因此这里的解决方案是创建一个允许您解析它的范围。
推荐阅读
- javascript - 如果不满足功能,如何停止 javascript 提示
- list - Haskell:为什么 (x:xs) 只匹配一个元素的列表?
- kdb - 如何从 kdb 中的 Date(yyyy.mm.dd) 获取 (mm.dd)?
- laravel - 如何将一种方法共享给 Laravel 中的所有控制器?
- python-3.x - 根据整数对列表进行排序返回错误的排序
- c++ - 从唯一指针到基类的派生类的decltype
- gensim - 大量行的相似矩阵的内存错误(gensim)
- voxel - 通过体素分析 3D 对象
- javascript - 修改由 jQuery 创建的输入
- postgresql - 如何使用子查询来考虑这个 postgis 查询?