Поймать конкретное исключение - PullRequest
14 голосов
/ 25 мая 2011

Как я могу поймать конкретное исключение, используя c #?
В моей базе данных есть уникальный индекс по некоторым столбцам.
когда пользователь вставляет повторяющуюся запись, это исключение выдается:

Невозможно вставить дубликат строки ключа в объект 'dbo. BillIdentity' с уникальным индекс «IX _BillIdentity». заявление было прекращено.

Как я могу поймать это исключение?
В настоящее время я проверяю, используя этот код:

 catch (Exception ex) {
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) {
        string ScriptKey = "$(function() {ShowMessage('Error');});";
        ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true);
    }
}

Я думаю, это плохой запах.
Есть ли лучший способ?

Ответы [ 6 ]

28 голосов
/ 25 мая 2011

Ручка SqlException только в этом случае.

[Изменить]

Чтобы проверить исключение повторяющегося ключа на сервере MS SQL:

try
{
    // try to insert
}
catch (SqlException exception)
{
    if (exception.Number == 2601) // Cannot insert duplicate key row in object error
    {
        // handle duplicate key error
        return;                  
    }
    else
        throw; // throw exception if this exception is unexpected
}

Edit: Откуда 2601?

select *
from sys.messages
where text like 'Cannot insert duplicate key%'

Возвращает:

message_id  language_id severity is_event_logged text
----------- ----------- -------- --------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2601        1033        14       0               Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls.

Используя exception.Number и ссылаясь на представление sys.messages, вы можете обработать любое конкретное исключение MS SQL.

15 голосов
/ 25 мая 2011

Вы не показали тип исключения, которое выдается, но вы можете перехватить этот конкретный тип исключения.Например:

catch (DuplicateKeyException e) {
    ...
}

Возможно, для не будет определенного типа исключения для , просто *1007* этой ошибки - но если вам нужно поймать что-то довольно общее, например SqlException, вы можетезатем ищите больше деталей внутри самого класса.Например, в SqlException есть свойство Errors, где вы можете посмотреть более подробную информацию о каждой из (возможно, множественных) ошибок на стороне базы данных.Каждый SqlError имеет свойство Number, которое будет указывать тип ошибки.Вы всегда можете вернуться к сообщению, если это абсолютно необходимо, но вам необходимо знать о возможности изменения сообщения для разных культур и т. Д.

Обратите внимание, что если вы на самом деле не Обрабатывая исключение, вы, вероятно, должны сбросить его:

catch (SqlException e) {
    if (CheckWeCanHandle(e)) {
        // Mess with the ScriptManager or whatever
    } else {
        throw;
    }
}
1 голос
/ 14 мая 2013

Я только что выбрал проект, по которому кто-то пошел по этому маршруту:

Catch ex As SqlException
    Select Case ex.Number
            Case 2601
                ...

Обратите внимание на следующее (из sys.messages в SQL Server):

2601 - Невозможно вставитьповторяющаяся строка ключа в объекте "%. * ls" с уникальным индексом "%. * ls".

Но как насчет этого??

2627 - Нарушение ограничения% ls '%.* LS'.Невозможно вставить дубликат ключа в объект "%. * Ls". "

Я просто потратил некоторое время на отслеживание именно этой проблемы.

А что, если мы сменим поставщика БД? Предположительно, 2601 не совсемуниверсальный ... Это воняет, ИМО. И если вы (были) сталкивались с этим на своем уровне презентации, я думаю, что есть более серьезные вопросы.

Если это должно бытьмеханизм выбора, похороните его глубоко, глубоко в DAL и позвольте настраиваемому Исключению просачиваться. Таким образом, изменения в хранилище данных (или, в идеале, этот механизм) имеют гораздо более ограниченную область действия, и вы можете обрабатыватьпоследовательно на уровне представления без каких-либо вопросов.

В настоящее время я склоняюсь к выполнению облегченного SELECT для идентификатора открытого соединения и избегаю исключения в целом.

0 голосов
/ 09 апреля 2019

Рабочий код только для фильтра, дублирование исключения нарушения первичного ключа

using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;

try {
    abc...
} catch (DbUpdateException ex) {
    if (ex.InnerException.InnerException is SqlException sqlEx && sqlEx.Number == 2601) {
        return ex.ToString();
    } else {
        throw;
    }
}

Примечание: мелкие детали: - ex.InnerException.InnerException не ex.InnerException

0 голосов
/ 25 января 2019

Как указано здесь , вы можете использовать фильтры исключений.Пример:

try
{ /* your code here */ }
catch (SqlException sqlex) when (sqlex.Number == 2627)
{ /* handle the exception */ }
0 голосов
/ 25 мая 2011

Вы можете поймать SqlException только для начинающих

catch (SqlException ex) {
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) {
        string ScriptKey = "$(function() {ShowMessage('Error');});";
        ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...