【问题标题】:.net core AddSingleton initialization.net core AddSingleton 初始化
【发布时间】:2021-11-08 21:19:57
【问题描述】:

我正在尝试注册一个单例类,在 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");
            });
        });

var efContext = x.GetService&lt;EFContext&gt;(); 被执行时,我得到了异常

System.InvalidOperationException: 'Cannot resolve scoped service 'EFContext' from root provider.'

感谢您在 OPCClient 类中注入 DbContext 的任何帮助

【问题讨论】:

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


【解决方案1】:

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

我建议将 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>();
   }
}

【讨论】:

  • 感谢您的提示,我试试看!我想知道它是否安全并且也可以将 DBContext 作为单例注入。执行对数据库的访问只是为了加载应用程序的一些配置,这些配置对于通过 gRPC 接口处理的所有请求都是通用的。多线程 gRPC iface 将无法访问数据库
  • 不使用 DBContext 作为单例可能会有一些问题 - 你会长时间保留 DbContext 的实例,不建议这样做。
  • 到目前为止,我只能通过使 DbContext 单例来使其工作。使用对 IServiceProvider 的引用,当我调用 GetRequiredService 时,我得到 System.InvalidOperationException: 'Cannot resolve scoped service 'EFContext' from root provider.'
  • 请记住,DbContext 持有与数据库的连接。在实际情况下,您有许多需要访问数据库的并发请求,并且将 DbContext 作为 Singleton 会导致问题。有什么特殊原因需要 OPCClient 成为单例吗?
猜你喜欢
  • 2019-10-20
  • 1970-01-01
  • 2020-06-26
  • 2020-05-11
  • 2021-09-11
  • 2019-11-09
  • 2014-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多