Regards,
Colin Ramsay
If you don’t implement Equals and GetHashCode properly you end up with newly created objects NOT being ejected from ISet(s) at creation, but failing to give you the ability to compare two entities (say from two different sessions) and have the correct result, or you end up with newly created objects being ejected from ISet(s) before they’ve been persisted:
Using Default Equals/GetHashCode (Inherited from Object):
1. Returns reference equality
2. New objects are always unique, they can be added to ISet(s) all day long before they’re persisted.
3. Once persisted, unless the object is actually the same in memory, Equals always returns false. Bad for the Union, etc. operators which make ISet(s) interesting.
Using Trivial Equals/GetHashCode:
1. Generally folks implement it against the Id field.
2. Before persistence, this is almost always 0, therefore newly created objects get ejected from ISet(s).
3. Using a more natural value (as recommended by most (N)Hibernate gurus) can be troublesome… if it’s not guaranteed unique, you can have issues, if it is, great. Sometimes, a table doesn’t properly have any unique values EXCEPT the key.
My solution, when either of the above won’t work, is to have two fields in my table, [Id] and [ObjectKey], which I implement in an abstract base class that all the other classes which require such tooling derive from. [Id] is your typical surrogate key, with all the cruft that goes along with that. The [ObjectKey] is a GUID, created by my object, so it’s guaranteed to exist BEFORE persistence. I use [ObjectKey] for Equals/GetHashCode.
I guess it might even make sense to just get rid of the [Id] field, and have the primary key be non-native (generated), but I’m pretty old school about using GUIDS as primary keys… don’t really like it; it’s too easy to slap a clustered index on that field when you’re not thinking about it (bad-bad).
My .02
- rb
<br