tags:

views:

65

answers:

1

Hi,

I'm currently using nHibernate and having a problem where two objects loaded separately but representing the same entity in the database do not have equal references.

See the following section of code for example:

CrudRepository<Customer> cr1 = new CrudRepository<Customer>();
Customer c1 = cr1.GetById(new Guid("0D19B0F0-CA41-4D4B-9FB9-9CF600F86A4B"));

CrudRepository<Customer> cr2 = new CrudRepository<Customer>();
Customer c2 = cr2.GetById(new Guid("0D19B0F0-CA41-4D4B-9FB9-9CF600F86A4B"));

if (c1.Equals(c2))
    MessageBox.Show("SAME!");   // True.

if (c1.GetHashCode().Equals(c2.GetHashCode()))
    MessageBox.Show("SAME!");   // True.

if (c1 == c2)
    MessageBox.Show("SAME!");   // False.

My interpretation of the nHibernate documentation lead me to believe that once you override the Equals() and GetHashCode() methods, nHibernate can load entities into the same reference.

This is the line I am referring to:

This only applies if these objects are loaded in two different ISessions, as NHibernate only guarantees identity ( a == b , the default implementation of Equals()) inside a single ISession!

I understand that (c1 == c2) is comparing the references of objects loaded at different times. However, I thought (and hoped) that nHibernate would automatically track pre-loaded references and update them accordingly.

Is this not true?

Or is there something I am doing wrong?

Thanks :)

NOTE: I use the singleton pattern to keep the same session throughout the application.

Edit: Every time I perform a CRUD task I use this NHibernateHelper class to get the single instance of the same session builder. This was an example piece of code.

public T GetById(Guid guid)
{
    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
        return session.Get<T>(guid);
    }
}

And this is my helper class:

public class NHibernateHelper
{
    private static ISessionFactory sessionFactory;

    private static ISessionFactory SessionFactory
    {
        get
        {
            if (sessionFactory == null)
            {
                var configuration = new Configuration();
                configuration.Configure();
                configuration.AddAssembly(typeof(Customer).Assembly);
                sessionFactory = configuration.BuildSessionFactory();
            }
            return sessionFactory;
        }
    }

    public static ISession OpenSession()
    {
        return SessionFactory.OpenSession();
    }
}
+2  A: 

You are creating a new session on every request (this is what your NHibernateHelper.OpenSession() method does) and nHibernate only guarantees reference equality within one session. Once you make sure that your requests are within the same session, the result of the two call will be the same object.

Thomas Lötzer
Thanks Thomas. I didn't notice that! Do you have any advice on session management? So that perhaps my collections that are already loaded can stay active? I ask this because I have seen other users mention that sessions shouldn't be kept open, and should be closed after each operation. What do you think?Thanks again.
Tony Day
After modifying the nHibernateHelper class to persist the session I found that the "Using" statement around my CRUD operations was closing the session. After fixing the issue you mentioned and the one with the "Using" my objects are now equal :) Thanks
Tony Day