views:

10

answers:

0

Hiya,

I'm implementing a layered supertype that all my entities will be based on. I am currently working on the Equity methods Equals and GetHashCode. I have the following for GetHashCode:

    public override int GetHashCode()
    {
        if (!_hashCode.HasValue)
        {
            if (this.Id.Equals(default(T)))
            {
                _hashCode = base.GetHashCode();

            }
            else
            {
                _hashCode = this.Id.GetHashCode();
            }
        }

        return _hashCode.Value;
    }

For entities retrieved from persistance there is no problems, the Id is used to generate a hash, and in the Equals member the Id value is used to test equality. If an entity is transient though (ie. hasn't been persisted to the DB yet) then it's Id value is null or zero. A hash code is created and saved for the lifetime of the object so that it remains immutable and so that even if the entity is persisted to the DB the original hash code is still used while it remains in memory.

This leads to a couple of problems though. First with the Equals member, if two transient entities are compared they will match, even though they may be different. A fix for this would be to implement some method that can be overridden that checks the properties of the rest of the two objects two determine if they are the same. It seems a shame to need to implement this just for this particular case though.

More importantly, if the transient object is persisted, but also remains in memory, and then the same entity is loaded again into the same collection, each of these objects will now have different hash codes (the formerly transient object still retaining it's original hash code from before it had an Id). This breaks the whole hash and hashtable function.

I would be interested to hear what people think as an alternative? I am currently thinking of implementing a GUID field in each entity to go along with the id field seen as though the id field is really a database implementation feature (an auto-incrementing key). If a GUID was implemented as an extra field in the DB which acts as kind of domain signature this could be assigned within the entities constructor at creation(or loading) and could be used by GetHashCode and Equals to always enforce equality. The downside is basically adding an extra identity column to the database (as I prefer using auto-incrementing integers as the primary keys for performance and readabilty reasons). Can anyone see a downside or alternative to this?

Cheers,

Steve