簡體   English   中英

PostgreSQL:命令已經在進行中

[英]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此處進行了包裝。

無論如何,我有我所擁有的(一個錯誤)。 所以,我的問題是如何避免此錯誤消息(我是關於“命令已經在進行中”)?

我對可能的決定有一些想法。 或許:

  1. DbDataReader設置為參數。 讀者的名字可以通過隨機function生成。但我不知道該怎么做。

  2. 等到當前進程完成並關閉閱讀器,然后運行第二個等等。但我不知道如何告訴新進程等到前一個進程完成。

所以,我需要你們的幫助,伙計們。

如果多個線程共享一個數據庫連接,則必須同步它們,以便只有一個線程同時使用該連接。 在 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連接的代碼之后定義了另一個名為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

我現在在定義第二個 DataReader 時使用它

    Dim cmdNom As New NpgSqlCOmmand(SQL, cn2)

NPGSQL 似乎拒絕多個集合......但接受多個連接!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM