NHibernate: Implementing Equals and GetHashCode

Conflicting advice abounds regarding the correct way to implement Equals and GetHashCode for NHibernate entities.

In general, any Equals implementation is required to be:

  • Transitive
  • Reflexive
  • Symmetric

A GetHashCode implementation must have the property that it returns the same value for any two objects for which Equals returns true (it may or may not return the same value for other object pairs).

One approach to determining equality is to compare each and every field between both entities. This approach doesn’t perform particularly well of course and, depending on the implementation, can be difficult to maintain.

I decided to base my Equals/GetHashCode implementation on object identity. All my entity objects are identified by a surrogate GUID that’s lazily initialized on first use. This allows me to implement the functionality in a base entity class and reuse it easily across all entities in the system:

public abstract class NHBEntity
{
    private Guid id;

    public virtual Guid Id
    {
        get
        {
            return (id == Guid.Empty) ? this.id = Guid.NewGuid() : this.id;
        }
        set
        {
            this.id = value;
        }
    }

    public override bool Equals(object obj)
    {
        if (obj == this) return true;

        var rhs = obj as NHBEntity;
        if (rhs == null) return false;

        return (this.Id.Equals(rhs.Id));
    }

    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
}

Being relatively new to NHibernate, I’m half anticipating having to make adjustments but so far this has worked well and, just as importantly, hasn’t been cumbersome to implement.

Comments are closed.