5

Какова наилучшая практика для обработки исключений в NHibernate?Обработка исключений NHibernate

У меня SubjectRepository следующим:

public void Add(Subject subject) 
    { 
     using (ISession session = HibernateUtil.CurrentSession) 
     using (ITransaction transaction = session.BeginTransaction()) 
     { 

      session.Save(subject); 
      transaction.Commit(); 
     } 
    } 

И юнит тест следующим образом:

 [Test] 
    public void TestSaveDuplicate() 
    { 
     var subject = new Subject 
     { 
      Code = "En", 
      Name = "English" 
     }; 

     _subjectRepository.Add(subject); 

     var duplicateSubject = new Subject 
     { 
      Code = "En", 
      Name = "English1" 
     }; 

     _subjectRepository.Add(duplicateSubject); 
    } 

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

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

В идеале я хотел бы иметь возможность поймать исключение и вернуть пользователю разумную ошибку на этом этапе. Существуют ли какие-либо задокументированные подходы к передовым методам обработки исключений NHibernate и отчетность перед пользователем о том, что пошло не так и почему?

Спасибо,

Matt

ответ

13

Я бы справиться с этим в методе Add как таковой:

public void Add(Subject subject) 
{ 
    using (ISession session = HibernateUtil.CurrentSession) 
    using (ITransaction transaction = session.BeginTransaction()) 
    { 
     try 
     { 
      session.Save(subject); 
      transaction.Commit(); 
     } 
     catch (Exception ex) 
     { 
      transaction.Rollback(); 
      // log exception 
      throw; 
     } 
    } 
} 

В блоке поймать, вы должны сначала откатить транзакцию и войти исключение. Тогда ваши варианты:

  1. Rethrow то же исключение, что и моя версия делает
  2. Заверните его в своем собственном исключение и бросить, что
  3. Ласточка исключение, ничего не делая, что очень редко хорошо идея

У вас нет реальных вариантов обработки исключения в этом методе. Предполагая, что пользовательский интерфейс вызывает этот метод, он должен вызывать его в своем собственном файле try..catch и обрабатывать его, отображая пользователю значимое сообщение об ошибке.Вы можете сделать свой тестовый тест с помощью атрибута ExpectedException (type).

Чтобы ответить на ваш вопрос напрямую, вы должны создать свою собственную «разумную ошибку», расширив Исключение и выбросьте это с исходным исключением как свое Внутреннее Исключение. Это метод обхода исключения, который я перечислял в (2).

+0

Я думаю, что исключение является лучшим вариантом. Внутреннее исключение - это что-то вроде строк сообщения MySQLException = «Дублировать запись« En »для клавиши 3». Поскольку это будет вызвано непосредственно передним концом, я хотел бы вернуть содержательное сообщение. – 2009-04-10 11:15:52

+0

Это хорошая идея, чтобы перехватить ВСЕ исключения и обернуть ее? – VikciaR

+0

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

1

Общий вопрос будет, что вы хотите, чтобы сообщить пользователю, и кто является пользователем?

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

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

Но в любом случае выбор того, как рассказать «пользователь», является вопросом уровня представления (уровень UI), а не для DAL. Возможно, вы должны исключить исключения из DAL в другом типе исключений, но только если вы собираетесь изменить сообщение. Вам не нужен ваш собственный класс исключений, если только ваши вызывающие лица не будут делать что-то другое, если это исключение доступа к данным, а не какое-то другое.

2

Все исключения Nhibernate не подлежат восстановлению, вы можете вернуться к дизайну слоя приложения/данных, если вы пытаетесь восстановить из исключений nhibernate. Вы также можете взглянуть на spring.net's exception translation implementaion Также вы вручную обрабатываете транзакции на исключениях, это утомительно и подвержено ошибкам, посмотрите на nhibernate's contextual sessions. У Spring.net также есть несколько приятных помощников вокруг nhibernate.

+0

Ссылка на конечную сессию NHibernate нарушена. –

+0

Рабочая ссылка для конечного сеанса NHibernate от archive.org: https://web.archive.org/web/20090327153540/http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/architecture.html –

1

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

Логика такова: исключения используются для указания исключительных обстоятельств, которые ваша программа не обслуживает. Пользователь, вводящий дублирующий код субъекта в приведенном выше примере, является тем, на что должна быть рассчитана ваша программа; поэтому, вместо того, чтобы обрабатывать исключение, поскольку ограничение БД нарушается (что является исключительным событием и не должно происходить), вы должны сначала обработать этот сценарий и только попытаться сохранить данные, когда знаете, что данные, которые вы Сохранение правильное.

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

Смежные вопросы