第一次使用Npgsql,虽然我已经完成了其他PostgreSQL编程。 Npgsql 3.1.6,PostgreSQL 9.5。 Visual Studio 2015与.Net 4.5.1。
我有一个看起来像这样的连接字符串(每次使用相同的字符串,未经修改,对于每次数据库连接尝试):
服务器= DBSERVER; SearchPath中=网络;数据库= NetInfo的;用户 ID = netuser;密码= netpassword;端口= 19491;的CommandTimeout = 300;池=真; MaxPoolSize = 75
这是我们网络的C#多线程数据收集器。收集器上最多运行32个线程。每个线程在需要时打开一个连接,但一次只使用一个连接。如有必要,线程将关闭并重新打开连接。我写了自己的各种连接池,它正在工作;在开始时打开一堆连接,从ConcurrentQueue
中拉出一个打开的连接,使用它,然后将其返回到队列中。队列中有16个开放连接。如果做得不对,那就充满了危险但是有效。在代码审查过程中,同事将我转向了Npgsql连接池,所以我正在尝试使用它。
当我到达UPDATE命令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);
}
}