We are also using Guids as "business identity", similar to Symon's
"lifetime identity". I try to follow this rule: If business needs an
identity, id should provide it. It should not depend on the
persistence layer implementation which manages the database identity.

This also means that the business logic often queries objects by this
guid, not by the id, which requires additional indizes and could make
it potentially slower. This is the price for the abstraction. Of
course, sometimes it will be practical and fast to use the database id
directly. This will be carefully chosen case by case.

Another approach is to remove the database generated id and only use
the guids that are generated by the business logic. This could be a
performance problem when inserting new records, because the guids are
not ascending values. This could be solved by using guid.comb. But I
don't have any experience with this.

On Dec 16, 11:29 am, "Symon Rottem" <[email protected]> wrote:
> 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 Rottemhttp://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