c# - 为什么我不能在需要相同上下文的 Controller 中注入(inject)需要 httpclient 和 EF 上下文的服务

标签 c# asp.net-core entity-framework-core

我有一个需要服务的 Controller ,所以我注入(inject)了它。该服务需要 HttpClient所以我注入(inject)它。他们都需要 EF 上下文。

我确实添加了 HttpClient在服务启动时。但是我有以下错误。

Startup :

services.AddHttpClient<IMyService, MyService>();

MyService

private readonly HttpClient _httpClient;
private readonly ReadContext _readContext;
public MyService(HttpClient httpClient, ReadContext readContext)
{
    _httpClient = httpClient;
    _readContext = readContext;
}

在我的 Controller 中:

private readonly IMyService _myService;
public MyController(ReadContext ctx, IMyService myService)
{
    _ctx = ctx;
    _myService = myService;
}

错误:

System.InvalidOperationException: Cannot resolve scoped service 'MyApp.Backend.ReadContext' from root provider.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.Extensions.Http.DefaultTypedHttpClientFactory`1.CreateClient(HttpClient httpClient)

当服务被注入(inject)到不需要 ReadContext 的 Controller 中时,情况并非如此。 ,这有效。这里似乎有一些解决循环。

更新

从评论中,我了解到 AddHttpClient<T>创建 T 的实例与 HttpClient 具有相同的生命周期由 aspnet core 创建和管理,它比 DbContext 长lifetime 这是实际请求的生命周期。很公平。那么我该如何注入(inject) HttpClient进入临时服务?

更新2

根据 blog我可以注入(inject) IHttpClientFactory 的实例在MyService而不是使用 services.AddHttpClient(); .事实上,错误消失了。我将不得不做一些阅读以了解向工厂询问 HttpClient 的实例之间的区别。或注入(inject)一个。

最佳答案

MyService 注册为作用域:

services.AddScoped<IMyService, MyService>();

然后,只需使用 MyService 注册您的 HttpClient:

services.AddHttpClient<MyService>();

您现在的做法是,MyService 是在单例范围内创建的,这使得无法像您的上下文一样注入(inject)范围内的依赖项。

或者,您可以注入(inject) IServiceProvider 并使用服务定位器反模式来获取上下文。它被称为反模式是有原因的,所以这不是解决问题的最佳方法,但如果您的服务是单例范围的,则没有其他方法:

public class MyService : IMyService
{
    private readonly HttpClient _client;
    private readonly IServiceProvider _services;

    public MyService(HttpClient client, IServiceProvider services)
    {
        _client = client;
        _services = services;
    }
}

然后,稍后:

using (var scope = _services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<ReadContext>();
    // do something
}

关于c# - 为什么我不能在需要相同上下文的 Controller 中注入(inject)需要 httpclient 和 EF 上下文的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52780587/

相关文章:

c# - 如何使用服务器端 Blazor 启用 Windows 身份验证

foreign-keys - 使用 Entity Framework 7 的流体 API 创建 optional 外键

c# - 从 DLL 文件中读取资源

c# - Kindle Fire 视频流式传输崩溃

c# - 根据计算改变时间

c# - 如何使用Net Core获取DbContext中的用户信息

entity-framework - EF7 (EFCore) 支持枚举吗?

c# - 避免默认构造函数和公共(public)属性 setter

c# - “输入末尾的语法错误”- 尝试从数据库启动存储过程时

database - Electron .Net核心。无法更新数据库。如何在Electron中配置sqlite或sql compact