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

Pr.*_*dor 5 c# entity-framework entity-framework-core ef-core-2.2

我正在使用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);
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

services.AddDbContextPool<EmployeeContext>(options => options.UseNpgsql(connection));
Run Code Online (Sandbox Code Playgroud)

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

Iva*_*oev 7

除了使用它的有争议的好处(从文档:“具有节约一定的DbContext实例的初始化成本的优势”),该的DbContext池根本就不是适用于您的情况,因为你的上下文包含状态这EF核心是不知道:

private readonly DatabaseSettings _databaseOptions;
Run Code Online (Sandbox Code Playgroud)

文档的“ 限制”部分明确指出:

警告!

如果在派生的DbContext类中维护自己的状态(例如,私有字段),则不应使用DbContext缓冲池,不应在请求之间共享该状态。EF Core只会在将DbContext实例添加到池中之前重置可识别的状态。


还有就是为什么有原因optionsActionAddDbContextPool需要,而对于AddDbContext它是可选的。这是由于上述限制,加上额外的要求,即DbContext派生类必须具有带有单个参数的单个 public构造函数。您可以通过用传递的空动作来欺骗来轻松地看到这一点: DbContextOptionsAddDbContextPool

services.AddDbContextPool<ApplicationDbContext>(options => { });
Run Code Online (Sandbox Code Playgroud)

但是在运行时,您会InvalidOperationException

无法合并类型为'ApplicationDbContext'的DbContext,因为它没有单个公共构造函数来接受类型为DbContextOptions的单个参数。

因此,为了有资格进行合并,您必须删除所有这些

private readonly DatabaseSettings _databaseOptions;
public ApplicationDbContext() { }
public ApplicationDbContext(IOptions<DatabaseSettings> databaseOptions)
{            
    _databaseOptions = databaseOptions.Value;
}
Run Code Online (Sandbox Code Playgroud)

并添加它

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
Run Code Online (Sandbox Code Playgroud)

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

换句话说,您的要求是相互排斥的,因此没有解决方案。