[英]PostgreSQL: command is already in progress
我的异步 function 尝试 select 表中的单个记录。 这个 function 接受从另一个 function 传过来的几个 arguments。
因此,一些进程(至少 6 个)可以同时使用它。 我经常收到一条错误消息“命令已经在进行中” 。
我知道问题隐藏在阅读器中,因为当另一个进程试图访问它时,阅读器很忙。
让我在下面发布完整的代码:
async private void InsertToLog(List<Printer> APrinter, List<PrinterToGridBinds> AGridBind, int index)
{
if (!String.IsNullOrEmpty(APrinter[index].Type.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extBatchNumber.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extBatchCounter.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extDIOCounter.Trim()))
{
string dio_count = "0";
string GetDIOCounter = string.Format(@"SELECT dio_counter FROM {0} WHERE device_type = '{1}' AND batch_number = '{2}' ORDER BY id DESC
LIMIT 1;", log_table_name, lst_PrinterStruct[index].Type, AGridBind[index].extBatchNumber);
try
{
NpgsqlCommand db_getCounter = new NpgsqlCommand(GetDIOCounter, conn);
if (conn.State != ConnectionState.Open)
conn.Open();
using (DbDataReader reader = await db_getCounter.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
dio_count = reader[0].ToString().Trim();
}
AGridBind[index].extDIOCounter = (Int32.Parse(dio_count) + Int32.Parse(AGridBind[index].extDIOCounter.Trim())).ToString();
string Insert_SQL = String.Format(@"INSERT INTO {0} (device_type, batch_number, start_date, batch_counter, dio_counter) VALUES ('{1}', '{2}', '{3}', '{4}', '{5}') ON CONFLICT ON CONSTRAINT unique_log_key DO UPDATE SET batch_counter='{4}', dio_counter='{5}';", log_table_name, APrinter[index].Type.Trim(),
AGridBind[index].extBatchNumber.Trim(), DateTime.Now.ToString(), AGridBind[index].extBatchCounter.Trim(), AGridBind[index].extDIOCounter.Trim());
var db_cmd = new NpgsqlCommand(Insert_SQL, conn);
int res = await db_cmd.ExecuteNonQueryAsync();
}
catch (Exception e)
{
string FMessage = String.Format("Printer {0} \r\n Can not write to table\r\n Error: {1}",
lst_PrinterStruct[index].Name, e.Message);
MessageBox.Show(FMessage);
}
finally
{
conn.Close();
}
}
}
正如您所看到的,阅读器通过using
此处进行了包装。
无论如何,我有我所拥有的(一个错误)。 所以,我的问题是如何避免此错误消息(我是关于“命令已经在进行中”)?
我对可能的决定有一些想法。 或许:
将DbDataReader
设置为参数。 读者的名字可以通过随机function生成。但我不知道该怎么做。
等到当前进程完成并关闭阅读器,然后运行第二个等等。但我不知道如何告诉新进程等到前一个进程完成。
所以,我需要你们的帮助,伙计们。
如果多个线程共享一个数据库连接,则必须同步它们,以便只有一个线程同时使用该连接。 在 PostgreSQL 数据库会话中一次只能运行一个语句。
由于同步很麻烦并且可能会损害您的并发性,因此您最好使用连接池,并且每个线程在需要时从池中请求一个连接。
将OleDB
程序迁移到PNGSQL
时,我在VB.Net
中遇到了同样的问题。
我的程序只执行了一个循环来读取简单的SQL SELECT
返回的一些记录。
'*******************************************************************
'* SelectMouvements()
'*******************************************************************
Private Function SelectMouvements() As Integer
SQL = _
<sql-select>
SELECT *
FROM mouvements
INNER JOIN comptes
ON comptes.no_compte = mouvements.personnal_account
LEFT OUTER JOIN cartes
ON cartes.no_carte = mouvements.no_carte
</sql-select>
Dim cmd As New NpgsqlCommand(SQL, cn)
Dim dr As NpgsqlDataReader
dr = cmd.ExecuteReader()
While dr.Read()
grid.Rows.Add()
With grid.Rows(iRow)
.Cells(0).Value = dr("communication")
...
End With
call NormalizeSomeFields(dr("name"))
End While
End Sub
使用OleDb
时我的代码不存在的问题是NormalizeSomeFields()
function 正在打开第二个DataReader
。
Private Sub NormalizeSomeFields(ByRef sNom as String)
SQL =
<sql-select>
SELECT NewNom
FROM aliasnom
WHERE Nom = <%= AddQuote(sNom) %>
<sql-select>
Dim cmdNom As New NpgSqlCOmmand(SQL, cn)
Dim drNom As NpgsqlDataReader
drNom = cmdNom.ExecuteReader()
If drNom.Read() Then
sNom = drNom(0)
End If
drNom.Close()
End Sub
该程序在cmdNom.ExecuteReader()
行上返回NpgsqlOperationInProgresException
。
解决方案
为了解决这个问题,我在定义cn
连接的代码之后定义了另一个名为NpgsqlConnection
的cn2
,如下所示
cn = New NpgsqlConnection(cs)
Try
cn.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
cn2 = New NpgsqlConnection(cs)
Try
cn2.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
我现在在定义第二个 DataReader 时使用它
Dim cmdNom As New NpgSqlCOmmand(SQL, cn2)
NPGSQL 似乎拒绝多个集合......但接受多个连接!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.