Удобные сообщения об ошибках при удалении строки с ограничением REFERENCE внешнего ключа - PullRequest
1 голос
/ 18 января 2012

Какова была бы лучшая практика для обработки удаления строки БД с ограничением FK REFERENCE? Моей целью было представить более удобные сообщения об ошибках конечному пользователю. Обратите внимание, что я t want to delete department with employees and that I don не хочу каскадно удалять таблицы.

Например, если у нас есть две таблицы:

-- Department table
CREATE TABLE [dbo].[Department](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
 CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

-- Employee table
CREATE TABLE [dbo].[Employee](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [DepartmentId] [int] NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[Employee]  WITH CHECK ADD  CONSTRAINT [FK_Employee_Department] FOREIGN KEY([DepartmentId])
REFERENCES [dbo].[Department] ([Id])
GO
ALTER TABLE [dbo].[Employee] CHECK CONSTRAINT [FK_Employee_Department]

И если кто-то хочет удалить строку из таблицы отделов, где эта строка указана в таблице сотрудников. Что делать?

  1. Перед выполнением оператора DELETE проверьте, есть ли ссылка на строку в таблице сотрудников, и корректно верните ошибку в GUI (при необходимости используйте список eployee)

  2. Выполните инструкцию DELETE и отловите исключение, например:

    catch (SqlException ex) 
    { 
        switch (ex.Number) 
           case 547: HandleErrorGracefully()
    } 
    
  3. Как-то иначе?

Было бы неплохо, если бы у кого-то был код / ​​ссылка на пример приложения ...

Ответы [ 4 ]

5 голосов
/ 18 января 2012

Вариант 3: сделать 1 и 2

Существует вероятность того, что кто-то вставит в другой процесс между проверкой (проходами) и неудачным удалением.

В этом случае вы можете просто сказать «извините, что-то пошло не так» пользователю (но зарегистрировать его), и посмотреть, не хотят ли они повторить попытку. Затем чек перехватит его.

2 голосов
/ 18 января 2012

Будьте милее!

Показывать отделы и количество сотрудников в нем, включайте опцию удаления, только если количество сотрудников равно 0.

Полагайтесь на ссылочную целостность для остановки ошибок кодирования, а непользовательские ...

0 голосов
/ 18 января 2012

У меня тоже была такая же проблема несколько дней / месяцев назад. После долгих поисков я пришел к решению о переводе сообщений об ошибках в DAL с использованием класса SqlHelper.

Я решил эту проблему следующим образом.

Создано несколько классов, которые были получены из класса Exception, как показано на диаграмме .

DalExceptionClass:Exception

ForeignKeyException: DalException

в SqlHelper

public void ExecuteNonQuery(string procedure)
{
    try
    {
      con.open()
       cmd.executenonquery();
      con.close();
      //Sql Exception is raised
    }
    catch(SqlException ex)
    {
        throw TranslateException(ex);
    }
}

используя код в ссылке, я перевел Sql исключения для DalException, а не исключения

protected DalException TranslateException(SqlException ex) { 
    DalException dalException = null; 

    // Return the first Custom exception thrown by a RAISERROR 
    foreach (SqlError error in ex.Errors) { 
        if (error.Number >= 50000) { 
            dalException = new DalException(error.Message, ex); 
        } 
    } 

    if (dalException == null) { 
        // uses SQLServer 2000 ErrorCodes 
        switch (ex.Number) { 
            case 2601: 
                // Unique Index/Constriant Violation 
                dalException = new DalUniqueConstraintException("{0} failed, {1} must be unique", ex); 
                break; 
            default: 
                // throw a general DAL Exception 
                dalException = new DalException(ex.Message, ex); 
                break; 
        } 
    } 

    // return the error 
    return dalException; 
} 

Обратите внимание, дело 2601:

Я отправил здесь заказное сообщение.

Теперь в моем DAL я буду обрабатывать только DalException, который вернет мне сообщение об исключении как

"{0} не удалось, {1} должен быть уникальным" с использованием string.Format (msg, «Вставка», «Клиент»);

это отправит исключение в BAL, так как «вставка не удалась, клиент должен быть уникальным», что может быть несколько гранулированным сообщением.

Редактировать

это будет обработано в DAL как

    public Client Insert()
    {
    try
       {
        _repository.Insert(client);
       } 
    catch(DalException ex)
       {
//wrap message since, error will always be in client entity as client's method is being called. Also, insertion is being failed.
         throw new BusinessException(string.Format(ex.message), "Insertion", "Client");
       }
    }

Ссылки

Как преобразовать сообщение SqlException в удобное для пользователя сообщение

http://www.reflectionit.nl/DAL.aspx

Какой должна быть стратегия для обработки исключений sql?

0 голосов
/ 18 января 2012

@ Ответ ГБН - хороший путь.Но вы также можете указать ON DELETE CASCADE в отношении внешнего ключа и задать пользователю что-то вроде «Вы уверены, что хотите удалить этот отдел и всех его сотрудников?».

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