如果所有配置都在 DbContext 的 OnConfiguring 方法中,如何使用 AddDbContextPool

How to use AddDbContextPool if all configuration in OnConfiguring method of DbContext

我正在使用 PostgreSQL,并且我有 ApplicationDbContext,例如:

public class ApplicationDbContext : DbContext
{
    private readonly DatabaseSettings _databaseOptions;
    public ApplicationDbContext() { }
    public ApplicationDbContext(IOptions<DatabaseSettings> databaseOptions)
    {            
        _databaseOptions = databaseOptions.Value;
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasPostgresExtension("citext");
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (_databaseOptions == null)
        {
            optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString());
        }
        else
        {
            optionsBuilder.UseNpgsql(_databaseOptions.ConnectionString,
            npgsqlOptionsAction: sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                    maxRetryCount: _databaseOptions.MaxRetryCount,
                    maxRetryDelay: TimeSpan.FromSeconds(_databaseOptions.MaxRetryDelay),
                    errorCodesToAdd: null);
            });
        }
    }
}

该上下文是许多其他上下文的基础。我正在改进性能并尝试使用上下文池。文档说要添加轮询我应该:

services.AddDbContextPool<EmployeeContext>(options => options.UseNpgsql(connection));

但我想在 OnConfiguring 方法中 store.UseNpgsql 和 DbContext 的其他配置。如何实现?

除了使用它的有争议的好处(来自文档:"has the advantage of saving some of the cost of initialization of DbContext instance"),DbContext pooling 根本不适用于您的场景,因为您的上下文包含 EF Core 不知道的 state

private readonly DatabaseSettings _databaseOptions;

并且文档的 Limitations 部分明确指出:

Warning!

Avoid using DbContext Pooling if you maintain your own state (for example, private fields) in your derived DbContext class that should not be shared across requests. EF Core will only reset the state that is aware of before adding a DbContext instance to the pool.


optionsAction of AddDbContextPool 是必需的,而 AddDbContext 是可选的,这是有原因的。这是因为上述限制,加上额外的要求,即您的 DbContext 派生 class 必须具有 single public 构造函数和 single DbContextOptions 参数。通过传递空操作来欺骗 AddDbContextPool,您可以很容易地看到:

services.AddDbContextPool<ApplicationDbContext>(options => { });

但是在运行时你会得到 InvalidOperationException

The DbContext of type 'ApplicationDbContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions.

所以为了符合合并的条件,你必须删除所有这些

private readonly DatabaseSettings _databaseOptions;
public ApplicationDbContext() { }
public ApplicationDbContext(IOptions<DatabaseSettings> databaseOptions)
{            
    _databaseOptions = databaseOptions.Value;
}

然后添加这个

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

现在你应该清楚为什么你问的是不可能的了。您的 OnConfiguring 方法需要 DatabaseSettings,但您无法提供它。因此 options 必须在外部配置。

也就是说你的要求是互斥的,所以没有解决方案。