Должен ли я проверять наличие ограничений в базе данных в коде или отлавливать исключения, генерируемые БД - PullRequest
16 голосов
/ 01 января 2009

У меня есть приложение, которое сохраняет данные в таблицу с именем Jobs. Таблица Jobs имеет столбец с именем Name, который имеет ограничение UNIQUE. Столбец Имя не является первичным ключом. Интересно, стоит ли мне самому проверять наличие дублирующихся записей, прежде чем пытаться сохранить / обновить новую запись, или лучше дождаться исключения, выдаваемого слоем доступа к данным. Я использую NHibernate для этого приложения, если это имеет какое-либо значение


Спасибо всем за отличный вклад.

Я нашел еще одну причину, по которой я должен проверять код, а не просто ждать, пока будет сгенерировано исключение (и поймано моим кодом). Похоже, что NHibernate будет выдавать только NHibernate.Exceptions.GenericADOException, который не очень информативен относительно причины исключения в этом случае. Или я здесь пропускаю аспект NHibernate?

Ответы [ 8 ]

14 голосов
/ 01 января 2009

Ответ: оба.

Если ваша база данных имеет ограничения, она может гарантировать определенные инварианты данных, такие как уникальность. Это помогает несколькими способами:

  • Если у вас есть ошибка в вашем приложение, нарушающее ограничение будет помечать то, что иначе не может быть замечен.

  • Другие пользователи базы данных могут предположить больше о поведении данные в соответствии с СУБД инварианты.

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

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

4 голосов
/ 02 января 2009

Если ваш дизайн хорош (и база данных, и BL), база данных не должна иметь каких-либо ограничений, которые не будут рассматриваться в BL - то есть вы не должны представлять базу данных с противоречивыми данными. Но нет ничего идеального.

Я обнаружил, что ограничение базы данных ограничениями согласованности данных позволяет мне обрабатывать все проверки BL в процедурном коде, и единственными случаями, когда у меня возникают исключения из базы данных, являются ошибки проектирования и кодирования, которые могут (и должны быть) исправлены.

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

3 голосов
/ 01 января 2009

Я бы оставил эту работу полностью в базе данных; Ваш код должен сосредоточиться на перехвате и правильной обработке исключения.

Причины:

  1. Производительность - База данных будет высоко оптимизирован для обеспечения соблюдения ограничения в быстром и эффективном путь. У тебя не будет времени оптимизировать ваш код.
  2. Ремонтопригодность - Если ограничения изменить в будущем, у вас не будет изменить свой код, или, возможно, вы просто нужно добавить новый улов {}. Если ограничение снято, вы не нужно трогать ваш код в все.
2 голосов
/ 01 января 2009

Если вы собираетесь проверить ограничения самостоятельно, сделайте это на уровне доступа к данным. Ничто над этим слоем не должно ничего знать о вашей базе данных или ее ограничениях.

В большинстве случаев я бы сказал, что предоставьте DAL возможность отлавливать исключения, возникающие из БД. Но в вашем конкретном случае, я думаю, мы говорим о базовой проверке входных данных. Я бы выбрал вызов проверки доступности имени в базу данных, прежде чем отправлять всю форму.

1 голос
/ 15 января 2010

Вопрос, на который вам нужно ответить:

«Нужно ли дарить пользователю приятные сообщения». Пример: уже есть задание с именем TestJob1. Если ответ Нет , просто поймайте ошибку и отправьте общее сообщение Если ответ Да , продолжайте читать

Если вы поймаете ошибку после вставки , недостаточно информации для представления правильного сообщения (по крайней мере, в агностическом БД)

С другой стороны, могут быть условия гонки , и вы можете иметь одновременную транзакцию, пытаясь вставить те же данные, поэтому вам нужно ограничение DB

Подход, который работает хорошо:

  • проверьте, прежде чем подарить сообщение
  • поймать исключение и представить общее сообщение об ошибке (при условии, что это не произойдет очень часто)
1 голос
/ 01 января 2009

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

Обычно рекомендуется проверять наличие исключений / ошибок, даже если вы уже все проверили раньше. Почти всегда есть что-то, что может пойти не так или что вы не учли в своем коде, но обеспечивается базой данных.

Редактировать: Если я правильно понял вопрос, речь идет не о том, должно ли ограничение применяться базой данных или нет, а о том, как справиться с ним в коде приложения. Конечно, вы должны всегда установить все ограничения в базе данных, чтобы предотвратить попадание неверных данных в вашу базу данных.

0 голосов
/ 16 апреля 2009

Внутреннее исключение GenericADOException расскажет вам, почему действие базы данных не удалось. Вы можете перехватить OracleException / MSSQLException / [InsertCustomExceptionHere] и обработать ошибку из этого сообщения. Если вы хотите передать это обратно во внешний интерфейс (при условии, что пользователь ввел дубликаты данных), вы можете сначала обернуть его в пользовательское исключение, чтобы не связывать свой внешний интерфейс с базой данных. Вы действительно не хотите передавать специфичные для СУБД исключения.

Я не согласен с проверкой БД на уникальность перед выполнением вставки. Двойное циклическое отключение базы данных не очень эффективно и, конечно, не масштабируется, если у вас большой объем пользовательского трафика.

0 голосов
/ 01 января 2009

Лично я бы поймал исключение. Это намного проще и требует гораздо меньше кода.

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