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

时间:2019-04-23 20:46:41

标签: 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);
            });
        }
    }
}

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

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

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

1 个答案:

答案 0 :(得分:7)

除了使用它的可争议的好处(来自文档:“具有节省DbContext实例初始化成本的优点” ),DbContext pooling根本不适用在您的方案中,因为您的上下文包含EF Core不知道的 state

private readonly DatabaseSettings _databaseOptions;

和文档的Limitations部分明确指出:

  

警告!

     

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


有一个理由要求optionsAction中的AddDbContextPool,而对于AddDbContext是可选的。这是由于上述限制,加上额外的要求,即您的DbContext派生类必须具有带有 single DbContextOptions参数的 single 公共构造函数。您可以通过传递空操作来愚弄AddDbContextPool

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

但是在运行时,您会得到InvalidOperationException的提示

  

“ ApplicationDbContext”类型的DbContext无法合并,因为它没有单个公共构造函数来接受单个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必须在外部配置。

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