【问题标题】:How to use AddDbContextPool if all configuration in OnConfiguring method of DbContext如果 DbContext 的 OnConfiguring 方法中的所有配置,如何使用 AddDbContextPool
【发布时间】:2019-09-13 02:36:40
【问题描述】:

我正在使用 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 的其他配置。如何实现?

【问题讨论】:

  • 您正在运行什么样的应用程序?它是一个 ASP.NET 应用程序吗?
  • 是的。 asp.net webapi

标签: c# entity-framework entity-framework-core ef-core-2.2


【解决方案1】:

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

private readonly DatabaseSettings _databaseOptions;

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

警告!

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


optionsActionAddDbContextPool 是必需的,而 AddDbContext 是可选的,这是有原因的。这是由于上述限制,以及您的 DbContext 派生类必须具有 single 带有 single DbContextOptions 参数的公共构造函数的额外要求。通过传递空操作来欺骗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

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

【讨论】:

  • 我怎样才能改变它?
  • 正如我所提到的,像您这样的上下文不符合上下文池的条件。换句话说,只需使用AddDbContext
  • 如果你需要这些DatabaseSettings,你不能。上下文池需要具有单个公共构造函数和DbContextOptions(或DbContextOptions&lt;TContext&gt;)参数的数据库上下文。所以你必须删除DatabaseSettings参数,但是你不知道如何在OnConfiguring中配置你的上下文,所以它必须在外部配置。如您所见,问题不是AddDbContextPool调用(可以很容易地用空操作调用),而是您的需求组合,没有解决方案。
  • 我不会说这没有解决方案 - 就像真的一样。 @Pr.Dumbledor,虽然@Ivan Stoev 对所有事情都是正确的,但我想说这取决于您是否可以妥协并在外部设置DatabaseSettings 选项,您在何时何地创建数据库上下文,您是否只需检查@ 987654345@ 选项不存在(传递给构造函数)并创建内存而不是真正的 Psql 数据库连接? MaxRetryCountMaxRetryDelay 总是相同吗?
  • @eja 但它们包含最重要的信息——连接字符串。没有它,OnConfiguring 基本上没有什么可以做的。这正是 OP 在帖子末尾想要的 - “但我想在 OnConfiguring 方法中存储.UseNpgsql 和 DbContext 的其他配置。如何实现?” 这听起来像是“没有解决方案”我:)
猜你喜欢
  • 2020-04-19
  • 2022-01-04
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
相关资源
最近更新 更多