ASP.NET Core 3.1中使用多个connectionString DI NpgsqlConnection postgreSQL的正确方法

Ngu*_*ong 6 c# postgresql dependency-injection connection-pooling asp.net-core

我正在努力使用, &NpgsqlConnection()中的多个连接字符串注册 DI 。ASP.NET Core 3.1Dapper v2.0.78Postgres v11

我将提供当前状态并修复以下代码:

当前状态

这个想法来自这里

步骤1Startup.cs --> ConfigureServices()

services.AddTransient<IDbConnectionFactory, DapperDbConnectionFactory>(sp =>
{
  var connectionDict = new Dictionary<DatabaseConnectionName, string>
  {
     { DatabaseConnectionName.Cnn1, "Connectionstring 1"},
     { DatabaseConnectionName.Cnn2, "Connectionstring 2"}
  };
  return new DapperDbConnectionFactory(connectionDict);
});
Run Code Online (Sandbox Code Playgroud)

第2步DapperDbConnectionFactory看起来像这样:

public class DapperDbConnectionFactory : IDbConnectionFactory
{
    private readonly IDictionary<DatabaseConnectionName, string> _connectionDict;

    public DapperDbConnectionFactory(IDictionary<DatabaseConnectionName, string> connectionDict)
    {
        _connectionDict = connectionDict;
    }

    public IDbConnection CreateDbConnection(DatabaseConnectionName connectionName)
    {
        string connectionString = null;

        if (_connectionDict.TryGetValue(connectionName, out connectionString))
        {
            return new NpgsqlConnection(connectionString); // <--- I think the issue comes from here
        }

        throw new ArgumentNullException();
    }
}
Run Code Online (Sandbox Code Playgroud)

第三步:我使用这段代码的方式:

public ConstructorMedthod(IDbConnectionFactory _connFactory)
{
   _conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1);
}
public async Task<QueryResult<IBaseReportModel>> Handle(...)
{
 ...
   var query = await _conn.QueryMultipleAsync("Query content here"); // <--- I think the issue comes from here
 ...
}
Run Code Online (Sandbox Code Playgroud)

我确实认为使用方式不正确,至少需要将调用包装_conn.QueryMultipleAsyncusing语句中以确保连接已关闭并释放,然后返回连接池。因为DI容器只是管理only的生命周期DapperDbConnectionFactory而不是IDbConnection

结果,有时我会收到此错误:

Npgsql.NpgsqlException (0x80004005):连接池已耗尽,请提高 MaxPoolSize(当前为 100)或超时(当前为 15 秒)

我必须重新启动应用程序然后它才恢复正常。所以我不确定问题是最大连接池还是网络超时。它应该能够检查池中的连接数与当时的最大连接池相比。我假设是这样。

修复代码

我有两个想法:

  1. 将调用包含_conn.QueryMultipleAsyncusing声明中。但这样我就必须在调用处改变太多代码_conn

  2. 改成DI的方式(想法来自这里)。更多详细信息如下。

步骤1Startup.cs --> ConfigureServices()

services.AddTransient<ServiceResolver>(serviceProvider => cnn_Name =>
{
    switch (cnn_Name)
    {
        case "Cnn1":
            return new NpgsqlConnection("Connectionstring 1");
        case "Cnn2":
            return new NpgsqlConnection("Connectionstring 2");
        default:
            throw new KeyNotFoundException();
    }
});

public delegate IDbConnection ServiceResolver(string connectionstring);
Run Code Online (Sandbox Code Playgroud)

第二步:我的使用方式:

private readonly IDbConnection _conn;

public ConstructorMedthod(ServiceResolver serviceAccessor)
{
   _conn = serviceAccessor(DbConnectionKey.Cnn1);
}

public async Task<QueryResult<IBaseReportModel>> Handle(...)
{
 ...
   var query = await _conn.QueryMultipleAsync("Query content here"); 
   // Now I suppose the _conn will be closed & disposed by DI container.
 ...
}
Run Code Online (Sandbox Code Playgroud)

问题

  1. 在 ASP.NET Core 3.1 中使用多个连接字符串注册 DINpgsqlConnection的正确方法是什么?postgreSQL

  2. 如何验证连接字符串是否返回连接池,Query on PostgreSQL例如这样这个

SELECT * FROM pg_stat_activity;
Run Code Online (Sandbox Code Playgroud)
  1. 如何将 增加到max connection pool大于 100。这是否是最佳实践?我发现这个帖子说的是

仅仅增加max_connections是个坏主意。你也需要增加 shared_bufferskernel.shmmax

但实际上,我使用的是AWS的RDS PostgreSQL。所以我想appsettings这样的配置。

用户ID = root;密码= myPassword;主机= localhost;端口= 5432;数据库= myDataBase;池= true;最小池大小= 0;Maximum Pool Size=200;

此外,正如这篇文章所说

Npgsql connection pooling is implemented inside your application process - it has nothing to do with PostgreSQL,这是完全没有意识到的。

所以我很困惑PostgreSQL(问题#2)和Appsettings(问题#3)之间的最大连接池

Ngu*_*ong 5

不幸的是,当前状态解决方案的作者

我不确定我是否正确使用了最佳实践,但我这样做是为了处理多个连接字符串。

详细阅读评论后,我认识到您必须使用using这样的声明。

public async Task<QueryResult<IBaseReportModel>> Handle(...)
{
 ...
     using(var conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1))
     {
       var response = await conn.QueryMultipleAsync("Query content here");
     }
 ...
}
Run Code Online (Sandbox Code Playgroud)

否则,你会得到这个错误

Npgsql.NpgsqlException (0x80004005):连接池已耗尽,请提高 MaxPoolSize(当前为 100)或超时(当前为 15 秒)

或者

“53300:剩余的连接插槽保留用于非复制超级用户连接”

突出显示的评论如下。希望它能帮助大家避免隐藏的错误。

在此输入图像描述

更新 - 2022-05-13

@Shay Rojansky 的回答中,我们已经澄清了混淆-和之间的问题 #3Appsetings -> Maximum Pool Size=200;PostgreSQL --> SHOW max_connections;

在此输入图像描述


归档时间:

查看次数:

15009 次

最近记录:

3 年,5 月 前