在ASP.NET Core 3.1中以正确的方式使用多个connectionString进行DI NpgsqlConnection postgreSQL。
在ASP.NET Core 3.1中以正确的方式使用多个connectionString进行DI NpgsqlConnection postgreSQL。
我正在努力在ASP.NET Core 3.1中注册具有多个连接字符串的DI NpgsqlConnection(),Dapper v2.0.78和Postgres v11。我将提供当前状态并修复下面的代码:\n
当前状态
\n
这个想法来自这里
\n步骤1。 Startup.cs --> ConfigureServices()
\n
services.AddTransient(sp => { var connectionDict = new Dictionary { { DatabaseConnectionName.Cnn1, "连接字符串1"}, { DatabaseConnectionName.Cnn2, "连接字符串2"} }; return new DapperDbConnectionFactory(connectionDict); });
\n步骤2。 DapperDbConnectionFactory
如下所示:\n
public class DapperDbConnectionFactory : IDbConnectionFactory { private readonly IDictionary_connectionDict; public DapperDbConnectionFactory(IDictionary connectionDict) { _connectionDict = connectionDict; } public IDbConnection CreateDbConnection(DatabaseConnectionName connectionName) { string connectionString = null; if (_connectionDict.TryGetValue(connectionName, out connectionString)) { return new NpgsqlConnection(connectionString); // <--- 我认为问题出在这里 } throw new ArgumentNullException(); } }
\n步骤3:我使用这段代码的方式:\n
public ConstructorMedthod(IDbConnectionFactory _connFactory) { _conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1); } public async Task> Handle(...) { ... var query = await _conn.QueryMultipleAsync("这里是查询内容"); // <--- 我认为问题出在这里 ... }
\n我确实认为使用方式不正确,需要至少将调用_conn.QueryMultipleAsync
的代码包装在using
语句中,以确保连接关闭和释放,然后返回连接池。因为DI容器只管理DapperDbConnectionFactory
的生命周期,而不是IDbConnection
的生命周期。\n结果有时会出现以下错误:\n
\nNpgsql.NpgsqlException (0x80004005):连接池已耗尽,请提高MaxPoolSize(当前为100)或Timeout(当前为15秒)\n
\n我不得不重新启动应用程序,然后它就恢复正常了。所以我不确定问题是因为最大连接池还是由于网络超时。应该能够检查池中的连接数与该时刻的最大连接池进行对比。我假设是这样的。\n
修复代码
\n我有两个想法:\n
- \n
- 将调用
_conn.QueryMultipleAsync
的代码包装在using
语句中。但是这种方式需要在调用_conn
的所有代码中进行太多的更改。 - 改变DI的方式(这个想法来自这里)。更多细节如下。
\n
\n
\n步骤1。 Startup.cs --> ConfigureServices()
\n
services.AddTransient(serviceProvider => cnn_Name => { switch (cnn_Name) { case "Cnn1": return new NpgsqlConnection("连接字符串1"); case "Cnn2": return new NpgsqlConnection("连接字符串2"); default: throw new KeyNotFoundException(); } }); public delegate IDbConnection ServiceResolver(string connectionstring);
\n步骤2:我使用的方式:\n
private readonly IDbConnection _conn; public ConstructorMedthod(ServiceResolver serviceAccessor) { _conn = serviceAccessor(DbConnectionKey.Cnn1); } public async Task> Handle(...) { ... var query = await _conn.QueryMultipleAsync("这里是查询内容"); // 现在我假设_DI容器将关闭和释放_conn。 ... }
\n
问题
\n
- \n
- 在ASP.NET Core 3.1中,如何正确注册具有多个连接字符串的DI NpgsqlConnection和postgreSQL?
- 我如何验证连接字符串是否返回到连接池,类似于在PostgreSQL上进行查询,例如这个和这个?
\n
\n
\n
SELECT * FROM pg_stat_activity;
\n
- \n
- 如何将最大连接池增加到大于100。是否是最佳实践?我在这篇帖子中发现说
\n
\n
\n仅增加
max_connections
是一个坏主意。您还需要增加shared_buffers
和kernel.shmmax
。\n
\n但实际上,我使用的是AWS的RDS PostgreSQL。所以我在考虑像这样配置appsettings
。\n
\nUserID=root;Password=myPassword;Host=localhost;Port=5432;Database=myDataBase;Pooling=true;Minimum\nPool Size=0;
Maximum Pool Size=200;
\n
\n此外,正如这篇帖子所说\n
\nNpgsql连接池是在您的应用程序进程内实现的 - 它与PostgreSQL完全无关。\n
\n所以我对于PostgreSQL中的最大连接池(问题#2)和Appsettings(问题#3)之间的理解非常困惑。
问题的出现的原因是作者在处理多个连接字符串时,不确定自己是否正确地使用了最佳实践。在详细阅读了评论后,发现必须像下面这样使用`using`语句:
public async Task> Handle(...) { ... using(var conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1)) { var response = await conn.QueryMultipleAsync("Query content here"); } ... }
否则,会出现以下错误:
Npgsql.NpgsqlException (0x80004005): The connection pool has been
exhausted, either raise MaxPoolSize (currently 100) or Timeout
(currently 15 seconds)
或者
"53300: remaining connection slots are reserved for non-replication
superuser connections"
希望这条突出显示的评论能帮助大家避免隐藏的错误。
更新 - 2022-05-13
从Rojansky的答案中,我们已经澄清了关于`Appsetings -> Maximum Pool Size=200;`和`PostgreSQL --> SHOW max_connections;`之间的混淆 - 问题#3。
[原文链接](https://stackoverflow.com/questions/44272459#comment127407163_44272654)
