Npgsql连接池在MinPoolSize连接处停止

第一次使用Npgsql,虽然我已经完成了其他PostgreSQL编程。 Npgsql 3.1.6,PostgreSQL 9.5。 Visual Studio 2015与.Net 4.5.1。

我有一个看起来像这样的连接字符串(每次使用相同的字符串,未经修改,每次数据库连接尝试):

Server = dbserver; SearchPath = network; Database = netinfo; User ID = netuser; Password = netpassword; Port = 19491; CommandTimeout = 300; Pooling = true; MaxPoolSize = 75

这是我们网络的C#multithreading数据收集器。 收集器上最多运行32个线程。 每个线程在需要时打开一个连接,但一次只使用一个连接。 如有必要,线程将关闭并重新打开连接。 我写了自己的各种连接池,它正在工作; 在开始时打开一堆连接,从ConcurrentQueue拉出一个打开的连接,使用它,然后将它返回到队列。 队列中有16个开放连接。 如果做得不对,那就充满了危险但是有效。 在代码审查期间,同事将我转向Npgsql连接池,因此我正在尝试使用它。

当我到达UPDATE命令(dbCommand.ExecuteNonQuery());时,我收到System.InvalidOperationException"The connection is not open" (dbCommand.ExecuteNonQuery()); 我不相信命令本身是重要的 – 这只是它击中的命令。 我注意到在DB服务器上netstat显示MinPoolSize + 1个开放套接字。 在上面的连接字符串中,它没有定义,所以MinPoolSize是1.我会在netstat中看到两个套接字。 如果我将MinPoolSize设置为16,我将看到17个套接字。 看起来Npgsql打开最小池大小,然后使用下一个连接抛出InvalidOperationException。 但它应该有多达75个连接可用,并在不可用时阻止。 不是。

我的PostgreSQL服务器上的最大连接数是100; 我远不及那个门槛。

它使用我自己编写的池共享方法时工作,因此执行查询的代码没有问题。 这就是我如何获得当前连接。

思考? 洞察? 谢谢!

编辑:根据要求。 。 。 它有点长,但它显示了几个相邻的条件,以了解流量。

 lock (ArpTableLocks.GetLock(nd.IdNd + " " + idMi + " " + idIf)) { if (_arpTableList.Get(nd.IdNd, idMi, idIf) == null) { // No device/MAC/IP/intf entry in DB, add one var dbConn = new NpgsqlConnection(DBStrings.connectionString); var dbCommand = new NpgsqlCommand(DBStrings.sqlARPTableInsert, dbConn); dbCommand.Parameters.Add(new NpgsqlParameter("@id_mi", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_nd", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_if", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters["@id_mi"].Value = idMi.ToString(); dbCommand.Parameters["@id_nd"].Value = nd.IdNd.ToString(); dbCommand.Parameters["@id_if"].Value = idIf.ToString(); var dbRead = dbCommand.ExecuteReader(); dbRead.Read(); idAt = dbRead.GetInt32(0); var arpTableListEntry = new ArpTableEntry { Id = idAt, IdNd = nd.IdNd, IdMi = idMi, IdIf = idIf }; _arpTableList.Add(arpTableListEntry); dbRead.Close(); dbConn.Close(); } } idAt = (_arpTableList.Get(nd.IdNd, idMi, idIf).Id); lock (ActiveArpTableLocks.GetLock(nd.IdV + " " + idAt)) { if (_activeArpTableList.Get(nd.IdV, idAt) == null) { var dbConn = new NpgsqlConnection(DBStrings.connectionString); NpgsqlCommand dbCommand = new NpgsqlCommand(DBStrings.sqlActiveARPTableInsert, dbConn); dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@seen", NpgsqlTypes.NpgsqlDbType.Timestamp)); dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString(); dbCommand.Parameters["@id_at"].Value = idAt.ToString(); dbCommand.Parameters["@seen"].Value = ae.TimeSeen; dbCommand.ExecuteNonQuery(); // Insert a history record dbCommand = new NpgsqlCommand(DBStrings.sqlHistoryARPTableInsert, dbConn); dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@firstseen", NpgsqlTypes.NpgsqlDbType.Timestamp)); dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString(); dbCommand.Parameters["@id_at"].Value = idAt.ToString(); dbCommand.Parameters["@firstseen"].Value = ae.TimeSeen; dbCommand.ExecuteNonQuery(); // Exception thrown here dbConn.Close(); Interlocked.Increment(ref _arpEntryAdded); } else { // DB has an active ARP table entry, so update its seen time. var dbConn = new NpgsqlConnection(DBStrings.connectionString); NpgsqlCommand dbCommand = new NpgsqlCommand(DBStrings.sqlActiveARPTableUpdateSeen, dbConn); dbCommand.Parameters.Add(new NpgsqlParameter("@seen", NpgsqlTypes.NpgsqlDbType.Timestamp)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4)); dbCommand.Parameters["@seen"].Value = ae.TimeSeen; dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString(); dbCommand.Parameters["@id_at"].Value = idAt.ToString(); dbCommand.ExecuteNonQuery(); dbConn.Close(); // Remove from activearptable hashtable _activeArpTableList.Delete(nd.IdV, idAt); Interlocked.Increment(ref _arpEntryUpdated); } }