NHibernate exception handling

What is the best practice for handling exceptions in NHibernate?

I have a SubjectRepository with the following:

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

And Unit Test as follows:

  [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); } 

I got to handling the error created by Unit Test and got a little stuck. This does not happen as expected, although with the exception of a GenericADOException, I was expecting a ConstraintViolationException or something similar (there is a uniqueness constraint for the theme code at the database level).

An ADOException wraps a MySQL exception that has a reasonable error message, but I don't want to start breaking encapsulation just by throwing an internal exception. In particular, since MySQL is not completed as the back of this project.

Ideally, I would like to catch an exception and return a reasonable error to the user. Are there any documented approaches to handling NHibernate exceptions and reporting to the user, what went wrong and why?

Thanks,

Matt

+6
exception exception-handling nhibernate unique-constraint
source share
4 answers

I would process it in the Add method as such:

 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; } } } 

In the catch block, you must first cancel the transaction and register an exception. Then your options are:

  • Repeat the same exception as my version
  • Wrap it in your own exception and throw it away
  • Swallow the exception without doing anything, which is very rarely a good idea.

You have no real options for handling exceptions in this method. Assuming the user interface calls this method, it should call it in its own try..catch file and process it, displaying a meaningful error message to the user. You can make your unit test pass using the ExpectedException (type) attribute.

To answer your question directly, you must create your own “reasonable error” by extending Exception and throwing it with the original exception as your InnerException. This is an exception circumvention method specified in (2).

+13
source share

All Nhibernate exceptions cannot be recovered; you can revert to the design of the application / data layer if you are trying to recover from nhibernate exceptions. You can also take a look at spring.net implementation of exception conversion. In addition, you manually process transactions on exceptions, it is tedious and error-prone, look at nhibernate contextual sessions . Spring.net also has some helpful helpers around nhibernate.

+2
source share

The general question will be, what do you want to tell the user and who is the user?

If the user is sometimes a different computer (i.e. this is a web service), then you will want to use the appropriate mechanism to return a SOAP Fault or HTTP error.

If the user will sometimes be some kind of user interface, you might want to display a message to the user, but what would you tell the user so that he can do something? For example, most websites will say, “Sorry, we had an unexpected error,” regardless of the reason. This is because the user usually cannot do anything with the error.

But in any case, the choice of how to say “user” is a matter for the presentation layer (UI layer), and not for the DAL. Perhaps you should exclude exceptions from the DAL in another type of exception, but only if you intend to modify the message. You do not need your own class of exceptions, unless your callers do something else, unless it is a data access exception, and not some other.

+1
source share

I would probably check the input before saving the object; Thus, you can implement any necessary validation (for example, check the length of the topic code, as well as the fact that there are no duplicates) and return significant verification errors back to the user.

The logic is this: exceptions are used to indicate exceptional circumstances that your program does not serve. The user entering the subject’s duplicate code in the above example is what your program should be designed for; therefore, instead of handling the exception, because the database restriction is violated (which is an exceptional event and should not happen), you should first process this script and only try to save the data when you know that the data you are saving is correct.

The advantage of implementing all the validation rules in your DAL is that you can ensure that the data coming into your database is valid in accordance with your business processes, rather than relying on restrictions in your database to catch this for you.

+1
source share

All Articles