如何在Singleton中使用DbContextPool?

时间:2019-03-19 18:18:53

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

在我的应用程序中,我正在使用NMS和ActiveMQ进行集成。 我有一些侦听器,它们是单例,正在侦听某些消息队列。 收到消息后,侦听器应对其进行处理并将其记录在数据库中。 我的DbContext是使用DbContextPool选项配置的:

        services.AddEntityFrameworkSqlServer();
        services.AddDbContextPool<MyContext>((serviceProvider, options) =>
        {
            options.UseSqlServer(connectionString);
            options.UseInternalServiceProvider(serviceProvider);
        });

因此,当我尝试将DbContext注入我的ActiveMqListener类中时,出现错误消息:

InvalidOperationException: Cannot consume scoped service 'MyApp.Data.MyContext' from singleton 'MyApp.Integrations.ActiveMqListener'.

在完成处理一条消息的工作后,如何获得池中的一个上下文并将其释放?还有其他推荐的方式吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

根据ASP.NET Core DI Service lifetimes文档:

  

从单例中解析作用域服务很危险。处理后续请求时,可能导致服务的状态不正确。

默认情况下,AddDbContextAddDbContextPoolDbContext注册为Scoped服务。您正在使用DbContext类中的ActiveMqListener,该类已注册为Singleton服务。那是问题!

解决方案是:通过ActiveMqListener方法将ScopedService注册为ASP.NET Core DI的Startup.ConfigureServices

注意:如果您必须将ActiveMqListener用作Singleton,请按照以下步骤将DbConext注册为Singleton

services.AddDbContext<MyContext>((serviceProvider, options) =>
        {
            options.UseSqlServer(connectionString);
            options.UseInternalServiceProvider(serviceProvider);
        }, ServiceLifetime.Singleton); // <-- Here it is