一个Scoped服务实例在.NET Core控制台应用程序中如何处理?

43

我从正在建设的 Web 应用程序的 ConfigureServices 中复制了这个内容。在此应用程序中,我试图摆脱 Web,只使用控制台应用程序或服务。

serviceCollection.AddScoped<IDbConnection, SqlConnection>(c => new SqlConnection(App.Configuration.GetConnectionString("DefaultConnection")));

控制台应用程序正常工作,但我想知道连接的生命周期是如何处理的。连接何时关闭或处置?或者它的行为与瞬态实例相同,我需要自己处理吗?


相关:https://dev59.com/fVcO5IYBdhLWcg3wiyGU - Michael Freidgeim
1个回答

54

当您从IServiceCollection(使用BuildServiceProvider方法)构建IServiceProvider并使用此IServiceProvider实例解析IDbConnection时,每次都会获得相同的IDbConnection实例。范围与IServiceProvider相关联。要创建新的范围,您需要从容器中解析IServiceScopeFactory并使用它来创建作用域IServiceProvider

using (var scope = scopeFactory.CreateScope())
{
   var scopedConnection = scope.ServiceProvider.GetRequiredService<IDbConnection>();      
}

当作用域被销毁时,连接将会被处理。

在ASP Core中,中间件为您管理范围,它创建新的范围,然后使用附加到该范围的IServiceProvider来解析控制器和此Web请求中的所有内容。在控制台应用程序中,您需要自己管理作用域。


1
一个 scopeFactory 如何与服务集合相连? - Thanasis Ioannidis
1
IServiceScopeFactory会被框架自动注册到IServiceCollection中,因此您无需手动注册。稍后,您可以直接从IServiceProvider中解析它。 - Krzysztof Branicki
2
创建作用域是否昂贵?我现在的情况是,我的代码(GraphQL解析器)需要存在于单例外部作用域中,但我需要获取一个作用域实例来引用HTTP请求。我唯一能想到的方法是创建自己的作用域并在其中解析,希望这不是一个昂贵的操作。 - benmccallum
如果您需要在单例模式下访问 HttpContext,则可以使用 IHttpContextAccessor。关于创建作用域的成本,我想您需要进行基准测试,但由于 ASP 为每个请求创建新的作用域,因此成本不会太高。 - Krzysztof Branicki
2
这是否意味着,对于控制台应用程序,AddScoped 依赖项会自动转换为单例,这就是为什么它们可以“自动地”工作,而无需创建显式范围? - JustAMartin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接