NHibernate & Null Object Pattern: The Options

Don’t bother using Null Object Pattern

The first option is to just not bother using Null Object Pattern, this is the easiest solution however has the side-effect that you end up with null checks everywhere which is the reason for moving to the Null Object Pattern in the first place.

Place a Null Object in the database

Next option is to have an object in the database that represents the null object so it will probably have an Id of zero and a value of << Unassigned >> or along those lines. This then has its own problems because if it’s a user editable object you don’t really want them to be able to change/delete this data so it becomes a special case that will need to be locked for editing/deleting.

Use Field Access and have the Property Handle the Mismatch

This is my preferred method whereby NHibernate is configured to use field access to the object, and the property handles the mismatch internally for example:

// inside class definition
protected User assignedTo;

public virtual User AssignedTo
{
    get
    {
        return assignedTo ?? User.NotAssigned;
    }
    set
    {
        if (value == User.NotAssigned)
            assignedTo = null;
        else
            assignedTo = value;
    }
}

This gives NHibernate a different view of the assigned to value than outside objects, for NHibernate which uses the internal field assignedTo it can be set to a null however for outside objects that have to use the AssignedTo property it will never be a null and instead will be set to the Null Object in this case User.NotAssigned.

Any other options please add a comment below 🙂

Advertisements

NHibernate code snippet

Here is a sample code snippet that you can use to generate a standard call to use an nHibernate ISession, you will need to make a small adjustment as to how you retrieve the ISession in your own projects.


      
    <Header>
        nHibernate block
        nhblock
        Code snippet for a standard NHibernate session call block
        Mike Cromwell
        
            Expansion
            SurroundsWith
        
     </Header>
    
        
             
        

        <Code>
            
        </Code>
      
    
 

Using Repositories with nHibernate

Intro

The point of this article is to demonstrate 2 ways that I have been using the Repository pattern in conjuction with nHibernate to provide my applications with rich domain objects, I wanted to also get feedback to the options shown and if there are any other ways to implement Repository with nHibernate.

Repository manages session

The first option and the one I used for the Staff Intranet and for older applications is wereby the repository manages the session object and decides where transactions should be used, here is an example of one the methods that we might typically see:

public int Save(User user)
{
    ISession session = NHibernateSessionManager.GetSession();
    ITransaction transaction = session.BeginTransaction();
    try
    {
        session.Save(user);
        session.Flush();
        transaction.Commit();
        return user.Id;
    }
    catch
    {
        transaction.RollBack();
        throw;
    }
    finally
    {
        NHibernateSessionManager.CloseSession();
    }
}

This has a number of the issues:

  • If you need to use a number of repositories in a single transaction this option will not work
  • Integration testing becomes more difficult as the repository handles the session and transactions

Caller manages session

The other way we can implement repositories is to let the calling code manage session and when transactions take place, here is an updated version of the above to accomodate the caller managing session & transactions:

public int Save(User user)
{
    ISession session = NHibernateSessionManager.GetSession();
    session.Save(user);
    session.Flush();
    return user.Id;
}

Our code has been reduced however the caller would now contain the code removed:

public int SaveUser(User user)
{
    ITransaction transaction = NHibernateSessionManager.GetSession().BeginTransaction();
    try
    {
        int userId = userRepository.Save(user);
        transaction.Commit();
        return userId;
    }
    catch (Exception thrownException)
    {
        transaction.RollBack();
        //... log exception, wrap up exception, rethrow, etc...
    }
    finally
    {
        NHibernateSessionManager.CloseSession();
    }
}

We could now quite happily make calls before or after the saving of the user to other repositories knowing that they would all be using the session & transaction.

I’m pretty convinced that this option of having the caller responsible for manageing session & transactions is a better way of implementing repositories, however if you of any other ways then please point me in the right direction 🙂

Helping Integration testing

One thing that I didn’t like having to do was performing integration tests against the database the reason being the extra care that needed to be taken to make sure that data was reverted back to the state it was to begin with, by using the caller in charge of session & transactions approach you can rollback any data changes made.

New Staff Intranet Release

I have found enough spare time to put up a new release of the staff intranet project, for those who are not aware of this project it is a demonstration of using best practices, principles & patterns in a real world web application so if your looking for pointers or some code to use for your own applications go give it a look on codeplex.

In this newest version I have added AOP support to cut down on cross cutting code and also the ability to delete staff members from the GridView, most of the time spent was fighting against the asp.net controls (suprise, surprise) such as the GridView and the ObjectDataSource, I’m not sure what the guy(s) who created the ObjectDataSource object was smoking at the time but it must have been stronger than just tobacco 🙂

My next release I want to demonstrate adding some service support showing how we can re-use existing code so they become little more than a remote facade (in theory!).

NHibernate exception: Unexpected row count: 0; expected: 1

While working on a project that uses NHibernate I was receiving the exception Unexpected row count: 0; expected: 1 after some investigation I found out that the problem was caused by me not setting an attribute in the mapping file.

I had a table in a sql server 2000 database that had an Id column this was set to an identity column, in my mapping file I had the following:


    

I kept getting the exception the moment I made a call to SaveOrUpdate using a new object that was associated with the table and then flushing the session, calls to already existing objects in the database were fine (Id property set) It turned out that because I was using -1 as the default for an object that was not saved NHibernate did not know that this was a new object to be inserted.

The fix was to change the mapping file to this: