random .NET and web development musings

There are plenty of discussions on why you should do this, which I’m not going to cover here.

What I am interested in discussing is a solution to the endless overriding of Equals and GetHashCode in each of your entities. Not only does this pollute the object with noise, but its a nightmare to maintain.

I use GUIDs for my Id columns, which is very convenient as you don’t have to goto the database for clues as to what the next unique ID may be.

Normally, when overriding GetHashCode you have to compare all your entity’s properties and when comparing for equality, you have to do the same because transient objects don’t yet have an ID.

This got me thinking, why even bother letting NH assign the ID? If you create the ID in your entities’ constructor GetHashCode and Equals become very easily overridden and can be abstracted to a base class, like so:

public abstract class Entity
{
	public virtual Guid Id { get; protected set; }

	protected Entity()
	{
		this.Id = Guid.NewGuid();
	}

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

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

		var entity = obj as Entity;
		if (ReferenceEquals(null, entity))
			return false;

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

For this to work, you must set your NHibernate ID Generator mapping to “Assigned”, like so:

<id name="Id" type="System.Guid">
    <column name="Id" />
    <generator class="assigned" />
</id>

For all you optimizers out there, you can still use alternate GUID algorithms like Comb :)

Thoughts?

2 COMMENTS
Victor Kornov
March 16, 2010
ad

That’s what I did with L2SQL 😉

March 16, 2010
ad

Once it occurred to me, it seemed too simple to be true! Glad you agree with the pattern :)

Post a comment