简体   繁体   English

PostgreSQL:命令已经在进行中

[英]PostgreSQL: command is already in progress

My asynchronous function tries to select a single record from a table.我的异步 function 尝试 select 表中的单个记录。 This function accepts a few arguments passed from another function.这个 function 接受从另一个 function 传过来的几个 arguments。

So, some processes (6 at least) can use it simultaneously.因此,一些进程(至少 6 个)可以同时使用它。 Often I get an error with the message "command is already in progress" .我经常收到一条错误消息“命令已经在进行中”

I know that the problem hides in the reader, because the reader is busy when another process tries to access it.我知道问题隐藏在阅读器中,因为当另一个进程试图访问它时,阅读器很忙。

Let me publish the full code below:让我在下面发布完整的代码:

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();
                }
            }
        }

As you can see, the reader is wrapped by using here.正如您所看到的,阅读器通过using此处进行了包装。

Anyway, I have what I have (an error).无论如何,我有我所拥有的(一个错误)。 So, my question is how to avoid this error message (I'm about "command is already in progress")?所以,我的问题是如何避免此错误消息(我是关于“命令已经在进行中”)?

I have a few ideas about possible decisions.我对可能的决定有一些想法。 Maybe:或许:

  1. Set the DbDataReader as parameter.DbDataReader设置为参数。 And the name of the reader can be generated by the Random function. But I don't know how to do that.读者的名字可以通过随机function生成。但我不知道该怎么做。

  2. Wait until the current process has finished and closes the reader, then run the second etc. But I don't know how to tell the new process to wait until the previous has finished.等到当前进程完成并关闭阅读器,然后运行第二个等等。但我不知道如何告诉新进程等到前一个进程完成。

So, I need your help, guys.所以,我需要你们的帮助,伙计们。

If several threads share one database connection, you have to synchronize them so that only one of them uses the connection at the same time.如果多个线程共享一个数据库连接,则必须同步它们,以便只有一个线程同时使用该连接。 You can only run one statement at a time in a PostgreSQL database session.在 PostgreSQL 数据库会话中一次只能运行一个语句。

Since synchronization is cumbersome and may hurt your concurrency, you'd be better off using a connection pool, and each thread requests a connection from the pool if it needs one.由于同步很麻烦并且可能会损害您的并发性,因此您最好使用连接池,并且每个线程在需要时从池中请求一个连接。

I have encountered same problem in VB.Net when migrating OleDB program to PNGSQL .OleDB程序迁移到PNGSQL时,我在VB.Net中遇到了同样的问题。

My program executed simply a loop to read some records returned by a simple SQL SELECT .我的程序只执行了一个循环来读取简单的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

The problem with my code that doesn't exist when using OleDb is that NormalizeSomeFields() function was opening a second DataReader .使用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

This program is returning NpgsqlOperationInProgresException on cmdNom.ExecuteReader() line.该程序在cmdNom.ExecuteReader()行上返回NpgsqlOperationInProgresException


SOLUTION解决方案


To solve this problem I have defined another NpgsqlConnection named cn2 just after code that is defining cn connection as in following lines为了解决这个问题,我在定义cn连接的代码之后定义了另一个名为NpgsqlConnectioncn2 ,如下所示

    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

and I use it now when second DataReader is defined我现在在定义第二个 DataReader 时使用它

    Dim cmdNom As New NpgSqlCOmmand(SQL, cn2)

NPGSQL seems to refuse multiple sets... but accepts multiple connections ! NPGSQL 似乎拒绝多个集合......但接受多个连接!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM