.net core AddSingleton初始化

gip*_*ani 0 c# entity-framework-core .net-core

我正在尝试注册一个单例类,在 Startup.ConfigureServices 方法中提供构造函数参数。

经过几次尝试,我仍然无法使 dbContext 注入工作

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
        services.AddDbContext<EFContext>();

        services.AddSingleton<OPCClient>(x =>
        {
            string endpointURL = "opc.tcp://xxx.yyy.zzz.nnn:12345";
            bool autoAccept = false;
            int stopTimeout = Timeout.Infinite;
            var efContext = x.GetService<EFContext>();

            OPCClient client = new OPCClient(endpointURL, autoAccept, stopTimeout, efContext);
            client.Run();

            return client;

        });
    }


    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // warmup
        app.ApplicationServices.GetService<OPCClient>();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapGrpcService<OPCService>();

            endpoints.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
            });
        });
Run Code Online (Sandbox Code Playgroud)

执行时var efContext = x.GetService<EFContext>();,我收到异常

System.InvalidOperationException: 'Cannot resolve scoped service 'EFContext' from root provider.'
Run Code Online (Sandbox Code Playgroud)

感谢您DbContextOPCClient课堂上注入的任何帮助

use*_*993 5

在单例中使用作用域服务(EFContext)并不是一个好的选择。DI 容器为每个请求创建一个作用域服务的新实例,而它只创建一次单例,这可能会导致对象状态不一致。文档在这里

我建议将 OPCClient 的生命周期更改为范围 - 使用 services.AddScoped 而不是 services.AddSingleton。如果您无法执行此操作,请传递 IServiceProvider 而不是 EFContext 的引用,并在每次需要使用该服务时从容器解析该服务:

public class OPCClient
{
   private IServicePrivder _serviceProvider;
   public OPCClient (IServiceProvider serviceProvider)
   {
     _serviceProvider = serviceProvider;
   }

   public void DoSomething() {
       EfContext efContext = _serviceProvider.GetRequiredService<EfContext>();
   }
}
Run Code Online (Sandbox Code Playgroud)