There are a couple of problems with this approach - it's pretty good, but I
it's still got a couple of holes.

There are a couple of issues:


1.  The cast in the equals method will not necessarily result in the type
you're expecting:



T other = obj as T;



If the current instance is a DomesticCat and the passed instance is a Cat
proxy that, in fact, represents a DomesticCat instance then the cast would
fail and return null because the Cat proxy cannot be cast to DomesticCat.
This could be worked around using the NHibernateUtils.GetClass(entity)
method, but that might cause performance issues since the DB would need to
be hit for proxies...



2.  This approach will still break if you have a transient entity that you
persist then evict from the Session thereby making it disconnected then
compare it with another loaded copy of same entity; the loaded entity and
the disconnected entity will be seen as equal but will have different
hashcodes breaking the contract which indicates that if equals() returns
true then hashcode comparison should also return true.

Certainly the approach will work for the majority of circumstances, but it's
probably worth being aware of the pitfalls just in case you fall into them.
:)

Personally I've worked around the problem by making a base class for my
entities that has a read only "lifetime id" property that's allocated a GUID
value at instantiation and is used for equality and hashcode comparisons.
Note that this property is *not* used as the identity map - my entities
still have an Id property for that.  The "lifetime id" property is persisted
and mapped using field access so the read only property can be set when a
persisted entity is loaded.

In effect, the GUID is generated when the transient instance is instantiated
and is then persisted with the object; at any point that the persistent
entity is reloaded the value is reloaded with it.  If the entity is evicted
from the session or the session is closed making it a disconnected entity
the lifetime id doesn't change.  If the entity is deleted and made transient
it still remains the same.  You could even re-persist it.

Of course, the drawback is that every entity row must now store an
additional GUID, however it's not necessary to have an index on this column
as it will never be searched, so it's not *too* expensive.  You might want
to make it unique, however, but I don't this it's essential as the
likelyhood of having two conflicting GUIDs in memory at the same time seems
rather low.

There may be a better way of handling this, but I haven't found it. :)

Cheers,

Symon.




On Tue, Dec 16, 2008 at 5:33 AM, Ayende Rahien <[email protected]> wrote:

> http://ayende.com/Blog/archive/2007/06/05/Generic-Entity-Equality.aspx
>
>
> On Mon, Dec 15, 2008 at 11:32 PM, Tim Barcz <[email protected]> wrote:
>
>> I am reading through a book on NHibernate (NHIbernate in Action, Manning)
>> and when talking about comparing entity values based on database identifier
>> (which is what EntityBase does) it strongly discourages equality based on
>> database Id's:
>>
>> Unfortunately, this solution has one huge problem: NHibernate doesn't
>>> assign identifier values until an
>>> entity is saved. So, if the object is added to an ISet before being
>>> saved, its hash code changes while it's
>>> contained by the ISet, contrary to the contract defined by this
>>> collection. In particular, this problem makes
>>> cascade save (discussed later in this chapter) useless for sets. We
>>> strongly discourage this solution (database
>>> identifier equality).
>>
>>
>> Generally DDD looks at an Entity's unique ID for determining equality.
>> However I'm a bit concerned at the strong warning from the NHibernate camp
>> about this type of equality comparison.
>>
>> What's the thought on this?  I'd be interested in hearing arguments on
>> either side.
>>
>> Tim
>>
>>
>
> >
>


-- 
Symon Rottem
http://blog.symbiotic-development.com

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to