PostgreSQL: команда уже выполняется - PullRequest
0 голосов
/ 05 апреля 2019

Моя асинхронная функция пытается выбрать одну запись из таблицы.Эта функция принимает несколько аргументов, переданных из другой функции.

Таким образом, некоторые процессы (не менее 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 в качестве параметра.И имя читателя может быть сгенерировано функцией Random .Но я не знаю, как это сделать.

  2. Подождите, пока текущий процесс не завершится и не закроет считыватель, затем запустите второй и т. Д. Но я не знаю, как сказатьновый процесс ожидания до завершения предыдущего.

Итак, мне нужна ваша помощь, ребята.

1 Ответ

1 голос
/ 05 апреля 2019

Если несколько потоков совместно используют одно соединение с базой данных, вы должны синхронизировать их, чтобы только один из них использовал соединение одновременно. Вы можете выполнять только один оператор за один раз в сеансе базы данных PostgreSQL.

Поскольку синхронизация обременительна и может нанести вред вашему параллелизму, вам лучше использовать пул соединений, и каждый поток запрашивает соединение из пула, если он ему нужен.

...