В моем проекте WinForms, написанном на C#, я подключаюсь к PostgreSQL базе данных, используя инфраструктуру Npg sql.
Я заполняю пару DGV с помощью DataTable из PG база данных. Я также пытаюсь реализовать функцию поиска, которая, по инициативе пользователя, ищет в таблице данных DGV строку поиска, а затем перестраивает DGV на основе этих результатов. Когда процесс выполняет поиск в DataTable, он формирует список идентификаторов записей (например, «1234,2345,3456»), которые будут переданы в запрос db для повторного заполнения DGV только теми записями, которые соответствуют поисковому значению пользователя.
Вот моя функция поиска, которая создает список идентификаторов и запрос базы данных:
private void btnSearch_Click(object sender, EventArgs e)
{
string searchText = txtSearchCatsGrid.Text;
string idToAddToList = "";
string tempIdList = "";
string idListForQuery = "";
DataTable dt = ((DataTable)dgvCategories.DataSource);
string cellValue;
int rowIndex;
int columnIndex;
for (rowIndex = 0; rowIndex <= dt.Rows.Count - 1; rowIndex++)
{
for (columnIndex = 0; columnIndex <= dt.Columns.Count - 1; columnIndex++)
{
cellValue = dt.Rows[rowIndex][columnIndex].ToString();
if (searchText == cellValue)
{
// Set corresponding dgvCategories cell's background color to yellow
dgvCategories[columnIndex, rowIndex].Style.BackColor = Color.Yellow;
idToAddToList = dt.Rows[rowIndex][0].ToString();
}
}
if (!string.IsNullOrEmpty(idToAddToList) && !tempIdList.Contains(idToAddToList)) tempIdList += idToAddToList + ",";
}
if (!string.IsNullOrEmpty(tempIdList))
{
// Remove the trailing comma that was added the last time an id was added to the list
idListForQuery = tempIdList.Remove(tempIdList.Length - 1, 1);
}
Console.WriteLine("idListForQuery: " + idListForQuery);
// Refresh dgvCategories with just rows from search, using idListForQuery
string companyFilter = cboSelectCompany.Text;
string categoryFilter = cboSelectCategory.Text;
db categoriesData = new db();
if (categoryFilter == "All Categories")
{
string catsQuery = "SELECT id, category, source_company, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
"FROM masterfiles.xref"+
" WHERE company_name = @company" +
" AND id IN (@idList)" +
//" AND id IN (SELECT UNNEST(@idList))" +
" ORDER BY category, old_value, source_company";
this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter, idListForQuery);
}
else
{
string catsQuery = "SELECT id, category, source_company, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
"FROM masterfiles.xref" +
" WHERE company_name = @company" +
" AND category = @category" +
" AND id IN (@idList)" +
//" AND id IN (SELECT UNNEST(@idList))" +
" ORDER BY old_value, source_company";
this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter, idListForQuery);
}
dgvCategories.DataSource = this.dtCategories;
if (dtCategories.Rows.Count == 0)
{
return;
}
else
{
dgvCategories.Columns[0].Visible = false;
dgvCategories.Rows[0].Cells[0].Selected = false;
}
}
Затем в моем классе базы данных функция GetDgvData () выглядит следующим образом:
public DataTable GetDgvData(string selectQuery, string companyFilter, string categoryFilter, string idFilter)
{
using (NpgsqlConnection conn = new NpgsqlConnection(connString))
using (NpgsqlCommand cmd = new NpgsqlCommand(selectQuery, conn))
{
cmd.Parameters.Add(new NpgsqlParameter("company", companyFilter));
if (!string.IsNullOrEmpty(idFilter)) cmd.Parameters.Add(new NpgsqlParameter("idList", idFilter);
//if (!string.IsNullOrEmpty(idFilter)) cmd.Parameters.Add("idList", NpgsqlDbType.Array | NpgsqlDbType.Integer).Value = idFilter;
//if (!string.IsNullOrEmpty(idFilter)) cmd.Parameters.Add(new NpgsqlParameter("idList", "ARRAY[" + idFilter + "]"));
if (categoryFilter != "All Categories") cmd.Parameters.Add(new NpgsqlParameter("category", categoryFilter));
conn.Open();
DataSet ds = new DataSet();
using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
{
da.Fill(ds);
}
return ds.Tables[0];
}
}
У меня проблемы с использованием этого списка идентификаторов в качестве параметра в запросе.
Вы заметите, что у меня есть несколько строк, закомментированных в обоих блоках кода. Это различные попытки передачи списка, все из которых приводят к ошибке в строке da.Fill(ds);
Когда я просто использую незакомментированную строку в коде построения запроса, AND id IN (@idList)
и «обычный» метод При добавлении параметра if (!string.IsNullOrEmpty(idFilter)) cmd.Parameters.Add(new NpgsqlParameter("idList", idFilter);
, также комментируемого в функции GetDgvData()
, ошибка в da.Fill(ds);
представляет собой NpgsqlPostgresException, «оператор не существует: целое число = текст».
После некоторых исследований я попытался функция UNNEST()
в коде запроса и оставил код параметра. Когда я пытаюсь это сделать, я получаю исключение, в котором говорится, что функция не существует.
После еще одного исследования я нашел пример кода, который преобразует тип Array db в Integer db Type, который является первой строкой. закомментированного кода в разделе параметров в функции GetDgvData()
. Когда я попытался это сделать, было выдано исключение: «System.InvalidCastException:« Не могу записать тип System.String в виде массива System.Int32 ».
После еще одного исследования я попробовал третий комментарий строка в функции GetDgvData()
, которая окружает параметр "Array[]"
. Исключение, которое я получаю за это: «оператор не существует: целое число = текст». Я попробовал это с и без функции UNNEST()
в запросе. Без UNNEST()
я получаю Npg sql .PostgresException, «оператор не существует: целое число = текст». Используя UNNEST()
, я получаю PostgresException, «функция unnest (text) не существует»).
Я также создал идентификаторы как List<>
и попытался передать его в GetDgvData()
, но я не передать его правильно или что-то, потому что я получаю исключение нулевой ссылки в GetDgvData()
, когда он попадает в строку, где я пытаюсь что-то сделать с List<>
- в том числе просто пытаюсь посмотреть содержимое в консоли.
Так что я действительно не знаю, что еще попробовать отсюда.
Другие успешно использовали приведенный выше код в своих соответствующих решениях, поэтому я могу только предположить, что что-то упустил, но что это может быть, я понятия не имею.