Combobox удваивает значение при заполнении базой данных - PullRequest
0 голосов
/ 11 июня 2018

Я использую C # Winforms и SQL Server в качестве базы данных.

В моем Combobox_Leave событии он заполнит другие Combobox текстовым значением предыдущего

Это одномоего Combobox_Leave события, оно похоже на другие Combobox

private void cmbPItem_Leave(object sender, EventArgs e)
{
    using (SqlConnection conn = new SqlConnection(@"Server=" + ip + "," + port + "; Database=records; User ID=" + sqlid + "; Password=" + sqlpass + ""))
    {
        conn.Open();
        using (SqlDataAdapter sda = new SqlDataAdapter(@"SELECT DISTINCT [Brand]
                                                        FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
        {
            DataTable dt = new DataTable();
            sda.Fill(dt);
            if (dt.Rows.Count != 0)
            {
                cmbPBrand.Items.Clear();
                for (int b = 0; b < dt.Rows.Count; b++)
                {
                    cmbPBrand.Items.Add(dt.Rows[b][0].ToString());
                }
            }
        }
        using (SqlDataAdapter sda = new SqlDataAdapter(@"SELECT DISTINCT [Manufacturer]
                                                        FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
        {
            DataTable dt = new DataTable();
            sda.Fill(dt);
            if (dt.Rows.Count != 0)
            {
                cmbPMan.Items.Clear();
                for (int m = 0; m < dt.Rows.Count; m++)
                {
                    cmbPMan.Items.Add(dt.Rows[m][0].ToString());
                }
            }
        }
        using (SqlDataAdapter sda = new SqlDataAdapter(@"SELECT DISTINCT [Car]
                                                        FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
        {
            DataTable dt = new DataTable();
            sda.Fill(dt);
            if (dt.Rows.Count != 0)
            {
                cmbPCar.Items.Clear();
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    cmbPCar.Items.Add(dt.Rows[i][0].ToString());
                }
            }
        }
        using (SqlDataAdapter sda = new SqlDataAdapter(@"SELECT DISTINCT [Year]
                                                        FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
        {
            DataTable dt = new DataTable();
            sda.Fill(dt);
            if (dt.Rows.Count != 0)
            {
                cmbPYr.Items.Clear();
                for (int y = 0; y < dt.Rows.Count; y++)
                {
                    cmbPYr.Items.Add(dt.Rows[y][0].ToString());
                }
            }
        }
        conn.Close();
    }
}

И вывод такой:

enter image description here

Когда пользователь нажимает на второй Combox, в этом примере cmbPBrand.Он заполняет Combobx дублированными значениями.Но когда пользователь нажимает другую Combobox, не выбирая какую-либо запись из cmbPBrand.Значения не дублируются.

enter image description here

Другой пример дублированных значений.

enter image description here

В этом cmbPYr нажимается после выбора из cmbPItem.Он дублирует значения DISTINCT.

Обратите внимание, что это происходит, когда пользователь CLICK второй Combobox.И я использую Leave Событие для моих Combobox.

Я также попытался добавить MouseClick и MouseDown и Enter и SelectedIndexChanged События.Но он все равно дублирует значения.

РЕДАКТИРОВАТЬ:

При использовании запроса

SELECT DISTINCT Brand,Manufacturer,Car,Year FROM [dbo].[products] WHERE Item LIKE 'BRAKE PADS'

Где cmbPItem.Text, например, равен BRAKE PADS.

enter image description here

Он запросит почти 675 строк.

enter image description here

РЕДАКТИРОВАТЬ: Что касается предложения Кевина.Это код только для бренда ComboBox, но он по-прежнему показывает повторяющиеся значения.

private void cmbProd_Enter(object sender, EventArgs e) {
    itemValue(cmbPItem.Text); }

private void itemValue(string sitem) {
    getBrand(sitem); }

private void getBrand(string sitem) {
    using (SqlCommand cmd = new SqlCommand(@"SELECT DISTINCT [Brand] FROM [dbo].[products] WHERE Item = @Item"))
    {
        cmd.Parameters.Add(new SqlParameter("Item", sitem));
        populateBrand(cmbPBrand, cmd);
    } }

private void populateBrand(ComboBox cmb, SqlCommand cmd) {
    using (SqlConnection conn = new SqlConnection(@"Server=" + ip + "," + port + "; Database=records; User ID=" + sqlid + "; Password=" + sqlpass + ""))
    {
        using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
        {
            cmd.Connection = conn;
            DataTable dt = new DataTable();
            sda.Fill(dt);
            if (dt.Rows.Count != 0)
            {
                cmb.Items.Clear();
                for (int b = 0; b < dt.Rows.Count; b++)
                {
                    cmb.Items.Add(dt.Rows[b][0].ToString());
                }
            }
            conn.Close();
        }
    } }

1 Ответ

0 голосов
/ 11 июня 2018

Я собираюсь предложить решение проблемы с несколько иной точки зрения.

Прежде всего, вы определенно должны подумать об изменении этих запросов для параметризации.Как я уже говорил, всякий раз, когда вы вводите необработанный ввод непосредственно в оператор SQL, вы открываете дверь для атак с использованием SQL-инъекций.Даже если это не основано на пользовательском вводе, все равно это плохая привычка.Выполнение параметризации SQL не сложно - это всего лишь одна дополнительная строка кода.

Следующее: рефакторинг вашего кода.Если я правильно вас понимаю, ваш код будет выглядеть следующим образом:

Event X
{
    13 or so lines to update Combo Box #1
    13 or so lines to update Combo Box #2
    13 or so lines to update Combo Box #3
    13 or so lines to update Combo Box #4
}
Event Y
{
    13 or so lines to update Combo Box #1
    13 or so lines to update Combo Box #2
    13 or so lines to update Combo Box #3
    13 or so lines to update Combo Box #4
}
Event Z
{
    13 or so lines to update Combo Box #1
    13 or so lines to update Combo Box #2
    13 or so lines to update Combo Box #3
    13 or so lines to update Combo Box #4
}
Event ... etc

Попробуйте поискать и поиграть с принципом единой ответственности (SRP) - это поможет вам написать более чистый и легкий в отладке код.

Когда это будет сказано и сделано?Тогда у вас есть хороший способ выяснить, в чем проблема: поместите несколько строк отладки в вашу функцию «UpdateBrandCombo ()» - место only , где обновляется поле со списком Brand (прямо сейчас, выу меня проблема в том, что любое из этих событий может обновлять поле со списком, и у вас нет действительно хорошего способа выяснить, что это делает.)

Что-то вроде:

Event X
{
    UpdateCombosWithSearch(cmbPItem.Text);
}
// ... later on ...
private void UpdateCombosWithSearch(string searchTerm)
{
    UpdateBrandCombo(searchTerm);
    UpdateMfgCombo(searchTerm);
    UpdateCarCombo(searchTerm);
}
private void UpdateBrandCombo(string searchTerm)
{
        SqlCommand sqlCmd = new SqlCommand("select distinct car from dbo.products where Item like @item");
        sqlCmd.Parameters.Add(new SqlParameter("item", searchTerm));
        SetComboBoxUsingQuery(cmbPBrand, sqlCmd);
}
private void SetComboBoxUsingQuery(ComboBox cbx, SqlCommand sqlCmd)
{
    cbx.Items.Clear();
    // code to get a DataTable from the sqlCmd
    // code to read the DataTable and add items to cbx
}

Видишь красоту?У вас нет повторяющегося кода.Все ваши события имеют одну строку: UpdateCombosWithSearch ().UpdateCombosWithSearch просто вызывает обновление для каждого поля со списком, которое необходимо обновить.И каждая из этих функций просто генерирует команду SQL и передает, в каком поле ее нужно обновить.Единственная функция, которая даже имеет какой-либо код SQL, - это функция SetComboBoxUsingQuery ().

Так что теперь вы можете добавить что-то вроде:

System.Diagnostics.Debug.WriteLine("Event logged by " + (new System.Diagnostics.StackTrace()).ToString());

... в одну из этих функций - так что выможно выяснить, где / когда / как вызывается ваш код обновления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...