Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407

Как обработать исключение Duplicate entry(MySql)

19.07.2023, 16:33. Показов 3750. Ответов 69
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть у меня функция для sql запроса в базу, например такая:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public static long AddNewDocument(int typeId, string name, string description, string fileName)
        {
            try
            {
                MySqlConnection con = new MySqlConnection(connStr);
                con.Open();
                string sql = @"INSERT INTO document (type_id, name, description, filename) 
                        VALUES (" + typeId + ", '" + name + "', '" + description + "', '" + fileName + "');";
                MySqlCommand command = new MySqlCommand(sql, con);
                command.ExecuteNonQuery();
                con.Close();
                return command.LastInsertedId;
            }
            catch (InvalidCastException e)
            {
                MessageBox.Show(e.Message);
                return -1;
            }
        }
Если name будет совпадать с тем, что в базе, то получаю подобное исключение:
Code
1
Duplicate entry 'исправления  Storage' for key 'name_UNIQUE'
В try-catch не ловится. В основном все ответы на эту тему связаны с тем, что в базу кидаются неправильно подготовленные данные, но в моем случае пользователь сам выбирает этот документ в OpenFileDialog, и это пользователь, может выбрать тот документ который уже есть в базе.
Вопрос в том можно ли как-то обработать это исключение без дополнительного проверочного запроса?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.07.2023, 16:33
Ответы с готовыми решениями:

Как в EF пропускать исключения дубликатов MySqlException: Duplicate entry '1-4' for key 'PRIMARY'
Добрый день. Используется EntityFramework с MySQL. Модель многие ко многим. В одной категории может быть много сайтов, один сайт может...

Duplicate entry mysql вставлять дубликаты
Здравствуйте. Есть таблица id | val | dop 1 | 1 | 1 2 | 1 | 2 3 | 2 | 2 4 | 1 | 1 <- тут будет при вставке ошибка...

MySQL Error! Duplicate entry '1' for key 'user_id_2'
Столкнулся с такой проблемой, если добавить коментарий к одной статьи, а потом к другой то вылазит такая ошибка MySQL error in file:...

69
Эксперт .NET
 Аватар для Usaga
14367 / 9468 / 1360
Регистрация: 21.01.2016
Сообщений: 35,721
20.07.2023, 11:31
Студворк — интернет-сервис помощи студентам
Andrey-MSK, вот тут точно не надо исключение кидать, если дубликат есть. Можно просто MessageBox показать. Это же не исключительная ситуация) Вполне себе ожидаемая.

И в catch не надо Rollback делать. Можно просто диспоузить транзакцию без Complete.
0
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 11:32  [ТС]
Usaga, Andrey-MSK, таких хитростей я не знал, спасибо, учту
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 11:35
Цитата Сообщение от Usaga Посмотреть сообщение
вот тут точно не надо исключение кидать, если дубликат есть.
Дак всё равно try .. catch используется, кинул
C#
1
throw new ApplicationException("Такой Вася уже есть. Позовите другого.");
,
а в catch
C#
1
MessageBox(ex.Message, "Ошибка");
Добавлено через 50 секунд
Ну и метод завершится, если Вася уже есть...
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 11:38  [ТС]
Usaga, только стоп, а как мне глобальный перехват исключений поможет в решении проблемы остановки метода? текст то я пользователю выдам, но метод в котором вызывался запрос продолжит работу после исключения и все
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 11:39
Цитата Сообщение от firnen_dragon Посмотреть сообщение
продолжит работу после исключения и все
Не продолжит, если будет throw выполнение прервётся.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 13:22  [ТС]
Andrey-MSK, посмотрел транзакции и throw написал что-то такое:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        public static long AddNewDocument(int typeId, string name, string description, string fileName)
        {
            MySqlConnection con = new MySqlConnection(connStr);
            con.Open();
            MySqlTransaction transaction = con.BeginTransaction(IsolationLevel.ReadCommitted);
            string sql = "SELECT COUNT(Name) FROM document where name like '" + name + "' LIMIT 1;";
            MySqlCommand command1 = new MySqlCommand(sql, con);
            command1.Transaction = transaction;
            sql = @"INSERT INTO document (type_id, name, description, filename) 
                        VALUES (" + typeId + ", '" + name + "', '" + description + "', '" + fileName + "');";
            MySqlCommand command2 = new MySqlCommand(sql, con);
            command2.Transaction = transaction;
            con.Close();
            try
            {
                int counter = Convert.ToInt32(command1.ExecuteScalar());
                if (counter > 0)
                {
                    throw new ApplicationException("Такой Вася уже есть. Позовите другого.");
                }
                command2.ExecuteNonQuery();
                transaction.Commit();
                return command2.LastInsertedId;
            }
            catch(ApplicationException ex)
            {
                transaction.Rollback();
                MessageBox.Show(ex.Message, "Ошибка");
            }
            con.Close();
            return -1;
        }
и внешний метод как работал дальше так и работает,может я плохо объясняю,по сем накалякал примерную схемку того, что нужно достичь, в данном случае throw никак не влияет на завершение внешнего метода, буду признателен, если подскажите где и что не так я делаю
Миниатюры
Как обработать исключение Duplicate entry(MySql)  
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 13:59
firnen_dragon, Пробуйте
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public static long AddNewDocument(int typeId, string name, string description, string fileName)
{
    MySqlConnection con = new MySqlConnection(connStr);
    MySqlTransaction transaction = con.BeginTransaction(IsolationLevel.ReadCommitted);
    string sql01 = "SELECT COUNT(*) FROM document where name = '" + name + "';";
    string sql02 = @"INSERT INTO document (type_id, name, description, filename)
                        VALUES (" + typeId + ", '" + name + "', '" + description + "', '" + fileName + "');";
    MySqlCommand command1 = new MySqlCommand(sql01, con, transaction);
    MySqlCommand command2 = new MySqlCommand(sql02, con, transaction);
    
    try
    {
        con.Open();
        int counter = (int)command1.ExecuteScalar();
        
        if (counter > 0)
        {
            throw new ApplicationException("Такой Вася уже есть. Позовите другого.");
        }  
        
        command2.ExecuteNonQuery();
        transaction.Commit();
        return command2.LastInsertedId;
    }
    catch (Exception ex)
    {
        transaction.Rollback();        
        MessageBox.Show(ex.Message, "Ошибка");
        
        // Вот это мне не нравится...
        return -1;        
    } 
    finally
    {
        con.Close();
    }   
}
И научитесь пользоваться параметрами...
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
20.07.2023, 14:02
Цитата Сообщение от firnen_dragon Посмотреть сообщение
что-то такое
1. Если после открытия соединения возникнет любая непредвиденная ошибка, то после выхода из метода соединение всё ещё будет оставаться открытым.
2. У вас подключение 'con' зачем-то закрывается до try-блока, а внутри try-блока используется 'command2', которому нужно это подключение.
1
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 14:06
firnen_dragon, И если не используете using, то finally нужно записать вот так
C#
1
2
3
4
5
6
7
8
finally
{
    con.Close();
    transaction.Dispose();
    command1.Dispose();
    command2.Dispose();
    con.Dispose();
}
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 14:22  [ТС]
kotelok,Да это я когда писал пост, исправил у себя в коде, а в посте забыл, это очепятка просто(это я про con.Close).
Andrey-MSK, return -1 мне и самому не нравится, но мне нужно вернуть id пслденнего добавленного документа, а,если есть try-catch, то приходиться еще и -1 возвращать иначе ошибка синтаксиса(не все ветви кода возвращают значение).
вашу переделку я попробовал, ну и итог тот же, честно говоря не очень понимаю как эта стратегия должна поспособствовать прерыванию внешнего метода.
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 14:28
Цитата Сообщение от firnen_dragon Посмотреть сообщение
как эта стратегия должна поспособствовать прерыванию внешнего метода
Так стоп. Вы этот метод вызываете еще где-то? Тогда catch по другому пишется... Вот пример тут есть с двумя методами - Какие есть практики по обработке exception
И это, con.Open(); поставьте перед MySqlTransaction transaction = con.BeginTransaction(IsolationLevel.ReadCommitted);
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 15:01  [ТС]
Andrey-MSK, Ооо, это то что нужно, спасибо за терпение, далеко не всегда въезжаю быстро, в итоге сделал так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        public static long AddNewDocument(int typeId, string name, string description, string fileName)
        {
            MySqlConnection con = new MySqlConnection(connStr);
            con.Open();
            MySqlTransaction transaction = con.BeginTransaction(IsolationLevel.ReadCommitted);
            string sql01 = "SELECT COUNT(*) FROM document where name = '" + name + "';";
            string sql02 = @"INSERT INTO document (type_id, name, description, filename)
                        VALUES (" + typeId + ", '" + name + "', '" + description + "', '" + fileName + "');";
            MySqlCommand command1 = new MySqlCommand(sql01, con, transaction);
            MySqlCommand command2 = new MySqlCommand(sql02, con, transaction);
 
            try
            {
                int counter = (int)command1.ExecuteScalar();
                command2.ExecuteNonQuery();
                transaction.Commit();
                return command2.LastInsertedId;
            }
            catch (MySqlException mysqlEx)
            {
                throw new ApplicationException(mysqlEx.Message);
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
            finally
            {
                con.Close();
            }
        }
Во внешнем методе обернул просто:
C#
1
2
3
4
5
6
7
8
9
            try
            {
                //Очень умные  вычисления и очень хорошо написанные запросы 
            }
            catch (Exception ex)
            {
                // Выводим ошибку и завершаем метод
                MessageBox.Show(ex.Message);
            }
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 15:01
Цитата Сообщение от firnen_dragon Посмотреть сообщение
а,если есть try-catch, то приходиться еще и -1 возвращать иначе ошибка синтаксиса(не все ветви кода возвращают значение)
Ну и у меня в примере возвращает int, но в catch ничего нет, кроме ошибки...
0
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 15:04  [ТС]
а стоп тогда мне получается это и не нужно:
C#
1
int counter = (int)command1.ExecuteScalar();
Я же могу просто вот так писать:
C#
1
command1.ExecuteScalar();
а в случае совпадения метод у меня прервется по идее

Добавлено через 1 минуту
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Ну и у меня в примере возвращает int, но в catch ничего нет, кроме ошибки...
Да, я уже увидел у вас, теперь возвращаю то, что нужно
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 15:04
Цитата Сообщение от firnen_dragon Посмотреть сообщение
а стоп тогда мне получается это и не нужно:
Ну по идее не нужно, метод сам выкинет исключение про дубликат. Это условие нужно было что-бы вывести удобоваримое сообщение...
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 16:07  [ТС]
Andrey-MSK, У меня еще вопрос появился, а могу ли я использовать тарнзакцию, когда у меня один запрос использует результаты второго?
Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        static public void AddContainer(int elementId, int count, int cellId, long operationId, string description)
        {
            MySqlConnection con = new MySqlConnection(connStr);
            try
            {
                con.Open();
                string sql = "SELECT name+1 FROM container WHERE name = (SELECT max(name) FROM container);";
                MySqlCommand command = new MySqlCommand(sql, con);
                string name = command.ExecuteScalar().ToString();
                string sql1 = "INSERT INTO container (name, element_id, count, cell_id, operation_id, description) VALUES (" + name + ", " + elementId + ", " + count + ", " + cellId + ", '"+ operationId + "', '" + description + "');";
                command = new MySqlCommand(sql1, con);
                command.ExecuteNonQuery();
            }
            catch (MySqlException mysqlEx)
            {
                throw new ApplicationException(mysqlEx.Message);
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
            finally
            {
                con.Close();
            }
        }
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 16:14
Цитата Сообщение от firnen_dragon Посмотреть сообщение
SQL
1
SELECT MAX(name) FROM container
Эммм, а смысл этого запроса? MAX() возвращает максимальный элемент, а что в этом случае он вернёт на текстовом поле?

Транзакции используются для вставки, удаления и модификации множества данных. Для одной записи, INSERT INTO () VALUES (), они не нужны, только если есть зависимость от текущего состояния таблицы...
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 16:30  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Эммм, а смысл этого запроса? MAX() возвращает максимальный элемент, а что в этом случае он вернёт на текстовом поле?
Да MAX() тоже можно но только тогда навеное MAX(name)+1.
Суть запроса:
Во-первых тут нужно понимать, что name содержит только числа(int) и по сути name - означает номер контейнера, но почему же тогда не использовать Id просто? Потому что контенер может дублироваться и прибывать в разных состояниях(например активный/не активный), таким образом выходит что контенеров может быть 1 , 2, 3.... и более и name у них у всех одно и тоже, а вот Id у них у всех разные, ну по этому я сначала запрашиваю последнее имя получаю 325 например прибавляю 1 и собственно создаю контейнер c новым именем, а id само инкрементируется

Добавлено через 1 минуту
Andrey-MSK, а вот зачем я его в стринг перегонял я даже и не знааю
0
 Аватар для Andrey-MSK
3371 / 2257 / 388
Регистрация: 14.08.2018
Сообщений: 7,647
Записей в блоге: 4
20.07.2023, 16:33
Цитата Сообщение от firnen_dragon Посмотреть сообщение
и по сути name - означает номер контейнера
А кто мешал назвать нормально? ContainerNumber например
Ну тогда поможет транзакция, только чтоб блокировала запись в таблицу на время работы. А то вдруг кто-то одновременно ещё запишет контейнер с таким-же номером...
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
20.07.2023, 17:03  [ТС]
Andrey-MSK,
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А кто мешал назвать нормально?
Та саму базу то не я делал, я с ней просто работаю, ну и к тому же есть приложения, которые работают с ней успешно, так что я лишний раз не рвусь в ее структуре что-то изменять.

А вот на счет транзакции так приемлемо?:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
static public void AddContainer(int elementId, int count, int cellId, long operationId, string description)
{
    MySqlConnection con = new MySqlConnection(connStr);
    con.Open();
    MySqlTransaction transaction = con.BeginTransaction(IsolationLevel.ReadCommitted);
    try
    {
        string sql = "SELECT name+1 FROM container WHERE name = (SELECT max(name) FROM container);";
        MySqlCommand command1 = new MySqlCommand(sql, con, transaction);
        string name = command1.ExecuteScalar().ToString();
        string sql1 = "INSERT INTO container (name, element_id, count, cell_id, operation_id, description) VALUES (" + name + ", " + elementId + ", " + count + ", " + cellId + ", '"+ operationId + "', '" + description + "');";
        MySqlCommand command2 = new MySqlCommand(sql1, con, transaction);
        command2.ExecuteNonQuery();
        transaction.Commit();
    }
    catch (MySqlException mysqlEx)
    {
        transaction.Rollback();
        throw new ApplicationException(mysqlEx.Message);
    }
    catch (Exception e)
    {
        transaction.Rollback();
        throw new ApplicationException(e.Message);
    }
    finally
    {
        con.Close();
        transaction.Dispose();
        con.Dispose();
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.07.2023, 17:03

Duplicate entry
Пытаюс выполнить запрос в MySQL сервере: INSERT INTO hosts (host, kod) VALUES ('ааааа', 1)Получаю ошибку: Duplicate entry '0' for key 1 ...

SqlExceptionHelper.logExceptions Duplicate entry
Запись создается но в stacktrace много ошибок , соответственно страницы не загружаются. Почему ? DROP SCHEMA IF EXISTS...

Duplicate entry '28' for key 'id_u'
Доброго времени суток! Столкнулся с проблемой, при добавлении вакансий пользователем на сайте. А именно: 1 пользователь не может добавить...

'Duplicate entry '0' for key 'PRIMARY''
Помогите с ошибкой... MySql.Data.MySqlClient.MySqlException: 'Duplicate entry '0' for key 'PRIMARY'' Она вылезает, когда я пытаюсь...

Ошибка Duplicate entry '10' for key 1
Есть скрипт добавление новостей. В файле конфига есть значение newsnum, которое регулирует количество выводимых на главную страницу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru