C# Выполнение 3 запросов на вставку MYSQL одним нажатием кнопки - данные из текстовых полей и списка

Мне было интересно, если вы можете мне помочь. Сначала я хотел сказать, что это мое первое приложение на C#, которое я создал, поэтому, пожалуйста, примите, что мой код не идеален.

Чего я хочу достичь: моим приложением будет приложение для управления ремонтом автомобиля. У меня есть панель, на которой у меня есть несколько текстовых полей и список. Одним нажатием кнопки я хочу сделать так, чтобы данные в текстовых полях были сохранены в таблице под названием "naprawa", а данные из списка были сохранены в таблице под названием "opisynapraw". Эти таблицы связаны с FK из "naprawa", поэтому я хочу, чтобы элементы из списка при их сохранении имели FK только что созданного поля в другой таблице. (Если это имеет смысл)

Пожалуйста, смотрите таблицу настройки ниже: Направа

|--------------+----------------+------+-----+---------+----------------+
| Field        | Type           | Null | Key | Default | Extra          |
|--------------+----------------+------+-----+---------+----------------+
| Nr_Naprawy   | int(11)        | NO   | PRI | NULL    | auto_increment |
| data_naprawy | date           | YES  |     | NULL    |                |
| nr_rej       | varchar(45)    | YES  | MUL | NULL    |                |
| Przebieg     | int(15)        | YES  |     | NULL    |                |
|--------------+----------------+------+-----+---------+----------------+

Данные в этой таблице:

|------------+--------------+---------+-----------|
| Nr_Naprawy | data_naprawy | nr_rej  | Przebieg  |
|------------+--------------+---------+-----------|
|      1     |  2018-06-20  | na06ysa |   150000  |
|------------+--------------+---------+-----------|

Таблица описания Praw:

+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| idopisynapraw | int(11)       | NO   | PRI | NULL    | auto_increment |
| Opis_Naprawy  | varchar(45)   | YES  |     | NULL    |                |
| Cena          | decimal(10,2) | YES  |     | NULL    |                |
| Nr_Naprawy    | int(11)       | YES  | MUL | NULL    |                |
+---------------+---------------+------+-----+---------+----------------+

Пример данных, которые я хотел бы видеть в этой таблице:

|---------------+--------------+-------+-------------|
| idopisynapraw | Opis_Naprawy | Cena  | Nr_Naprawy  |
|---------------+--------------+-------+-------------|
|       1       |  notes abcd  |  30   |      1      |
|---------------+--------------+-------+-------------|
|       2       |  notes cdef  |   5   |      1      |
|---------------+--------------+-------+-------------|

Что я хочу, чтобы мой код делал. Когда я нажимаю кнопку "Добавить", она добавляет запись из текстовых полей в "naprawa". Затем возьмите идентификатор того, что было добавлено, и используйте его как FK для opisynapraw и добавьте его вместе с данными из listveiw в таблицу opisynapraw.

Вот мой код

private void btnDodajNaprawe_Click(object sender, EventArgs e)
        {
            try
            {
                MySqlConnection myConn3 = new MySqlConnection(MyConnection);

                myConn3.Open();



                string querydoajnap = "INSERT INTO naprawa (data_naprawy,nr_rej,Przebieg) VALUES('" + dtaData.Value.Date.ToString("yyyy/MM/dd") + "', '" + txtNrRej.Text + "', '" + txtPrzebieg.Text + "');";
                MySqlCommand cmd = new MySqlCommand(querydoajnap, myConn3);

                MySqlConnection lastidconn = new MySqlConnection(MyConnection);
                lastidconn.Open();


                if (cmd.ExecuteNonQuery() == 1)
                {
                    MessageBox.Show("Dodane");


                    txtNrRej.Text = string.Empty;
                    txtPrzebieg.Text = string.Empty;

                }
                else
                {
                    MessageBox.Show("Blad");
                }




                String LastIDnapr = "select LAST_INSERT_ID();";
                MySqlCommand cmd1 = new MySqlCommand(LastIDnapr, lastidconn);
                MySqlDataReader IDRead = cmd1.ExecuteReader();
                int idnumber = 0;
                while (IDRead.Read())
                {
                    idnumber = IDRead.GetInt32(0);
                }

                MySqlCommand cmd2 = myConn3.CreateCommand();

                foreach (ListViewItem item in listView1.Items)
                {
                    // opisynapraw(Opis_Naprawy,Cena,Nr_Naprawy) VALUES (@val1 , @val2, '" + idnumber + "');";


                    cmd2.Parameters.AddWithValue("@val1",item.Text);
                    cmd2.Parameters.AddWithValue("@val2",item.SubItems[1].Text);
                    cmd2.CommandText = "INSERT INTO opisynapraw(Opis_Naprawy,Cena,Nr_Naprawy) VALUES (@val1 , @val2, '" + idnumber + "');";
                    cmd2.ExecuteNonQuery();
                }
                lastidconn.Close();
                myConn3.Close();


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Когда я выполняю приведенный выше код, он работает для добавления данных в таблицу "Naprawa", но я думаю, что он не будет использовать последний использованный идентификатор для связи с таблицей "opisynapraw", что приводит к следующей ошибке.

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

Невозможно добавить или обновить дочернюю строку; сбой внешнего ключа ('cars','opisynapraw', CONSTRAINT 'Nr_Naprawy'FOREIGN Key ('Nr_Naprawy') ССЫЛКИ'naprawa'('Nr_Naprawy') ON УДАЛИТЬ НЕТ ДЕЙСТВИЙ ОБ ОБНОВЛЕНИИ НЕТ ДЕЙСТВИЙ)

Я был бы очень признателен за любую помощь в разрешении этой тайны.

Заранее спасибо

Rogupl

2 ответа

Решение

Вам нужно INSERT в Naprawa, чтобы вернуть вам автоматически сгенерированное значение в том же запросе. Добавьте это в конец вашего оператора вставки, после ;

SELECT LAST_INSERT_ID();

Затем, чтобы получить его обратно, измените ExecuteNonQuery в ExecuteScalar - возвращаемое значение будет тем значением, которое вам нужно - оно возвращает его как объект, поэтому либо приведите его, либо System.Convert Это. (Это требует, чтобы вы удалили свой чек, что он вставил 1 строку; но имейте в виду, что он выдаст исключение, если он потерпит неудачу.)

Теперь удалите код, относящийся к LastIDnapr запрос, он должен работать нормально.

Дополнительные советы:

  1. Ваш код уязвим для атак с использованием SQL-инъекций: используйте параметры SQL вместо конкатенации строк для создания запроса.
  2. MySqlConnection, MySqlCommand и MySqlDataReader все IDisposable, поэтому каждый должен быть в using блок.
  3. Эти соединения подключаются к одной базе данных, поэтому убедитесь, что они не перекрываются. Это будет очевидно, как только вы используете using блоки.
  4. Посмотрите, можем ли мы прекратить использовать AddWithValue

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

Но давайте вернемся к вашей проблеме, я твердо верю, что вы пытаетесь вставить id в таблицу opisynapraw, которой нет в table naprawa как id. Пожалуйста, проверьте, какой идентификатор вы получаете, что вы пытаетесь вставить, и подтвердите его данными базы данных.

Другие вопросы по тегам