<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>
<channel>
	<title>Comments on: On Choosing an Identity (type!)</title>
	<atom:link href="http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/feed/" rel="self" type="application/rss+xml" />
	<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/</link>
	<description>Miscellaneous musings on life, .NET development, and related things that don't really matter</description>
	<pubDate>Thu, 17 May 2012 21:36:45 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: sbohlen</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-18735</link>
		<dc:creator>sbohlen</dc:creator>
		<pubDate>Sun, 19 Jul 2009 16:38:53 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-18735</guid>
		<description>@Brian:

*Generally* speaking, you are describing the (age-old) database design debate about the difference between 'natural' ( http://en.wikipedia.org/wiki/Natural_key ) and 'surrogate' ( http://en.wikipedia.org/wiki/Surrogate_key ) primary keys in the table.

Setting aside the fact that this has been the subject of many religious wars over the years, I am a fan of the 'surrogate' key approach where the PK value has zero semantic business meaning (you can read either of those wikipedia links for ideas as to why I feel this way) and so my choice of data type for PK is independent of what a user might expect/want to try to remember.

Thanks for the feedback and I'll be glad to accept any (big or small) donation if/when you can -- every little bit helps~!

Thanks again,

-Steve B.</description>
		<content:encoded><![CDATA[<p>@Brian:</p>
<p>*Generally* speaking, you are describing the (age-old) database design debate about the difference between &#8216;natural&#8217; ( <a href="http://en.wikipedia.org/wiki/Natural_key" rel="nofollow">http://en.wikipedia.org/wiki/Natural_key</a> ) and &#8217;surrogate&#8217; ( <a href="http://en.wikipedia.org/wiki/Surrogate_key" rel="nofollow">http://en.wikipedia.org/wiki/Surrogate_key</a> ) primary keys in the table.</p>
<p>Setting aside the fact that this has been the subject of many religious wars over the years, I am a fan of the &#8217;surrogate&#8217; key approach where the PK value has zero semantic business meaning (you can read either of those wikipedia links for ideas as to why I feel this way) and so my choice of data type for PK is independent of what a user might expect/want to try to remember.</p>
<p>Thanks for the feedback and I&#8217;ll be glad to accept any (big or small) donation if/when you can &#8212; every little bit helps~!</p>
<p>Thanks again,</p>
<p>-Steve B.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-18730</link>
		<dc:creator>Brian</dc:creator>
		<pubDate>Sun, 19 Jul 2009 12:37:21 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-18730</guid>
		<description>Quick question that may be borne out of ignorance but I have developed at least 2 apps where the user expects to be able to find something by id. Is this a valid reason to use an incrementing int in your table either as primary key or alongside a GUID?

Its an amusing thought if you are dealing with a customer who has submitted a ticket on your crm and you say "can you call out the GUID to me?".

Fantastic series Steve both on Agile and nHibernate. Really valuable to me in my efforts to learn more. As soon as my credit card statement looks a bit healthier I'm going to donate a few euro :)</description>
		<content:encoded><![CDATA[<p>Quick question that may be borne out of ignorance but I have developed at least 2 apps where the user expects to be able to find something by id. Is this a valid reason to use an incrementing int in your table either as primary key or alongside a GUID?</p>
<p>Its an amusing thought if you are dealing with a customer who has submitted a ticket on your crm and you say &#8220;can you call out the GUID to me?&#8221;.</p>
<p>Fantastic series Steve both on Agile and nHibernate. Really valuable to me in my efforts to learn more. As soon as my credit card statement looks a bit healthier I&#8217;m going to donate a few euro <img src='http://unhandled-exceptions.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sbohlen</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-16759</link>
		<dc:creator>sbohlen</dc:creator>
		<pubDate>Mon, 08 Jun 2009 20:18:53 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-16759</guid>
		<description>@Marc Scheuner:

Yep, I completely respect Kim's expertise when it comes to tuning SQLServer for performance and so I'm well-aware of what she's suggesting here: that randomly-ordered PKs are awful in re: the performance of SQL Server indexing and I don't dispute this point at all as all the literature would (and my own experience) would certainly back her up on this.

This is why I make use of the Guid.Comb generator for identity (PK) values in my NHibernate-based solutions.  Guid.Comb results in a unique yet also ever-increasing value for the identity which is what Kim is suggesting at the end of her post here...

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain!.aspx

...in which she suggests that under SQL Server 2005 (and also SQL Server 2008, of course) one should choose the newsequentialid() method over the completely random newid() method in the database.

The Guid.Comb identity generator in NHibernate is essentially the non-database-dependent version of the SQL Server newsequentialid() function that can be invoked client-side without requiring a database round-trip just to get a new PK for an entity.

The idea of using a separate INT IDENTITY column in the DB along with the Guid as PK and having the clustered index depend on this INT value is an interesting one I hadn't considered before -- are you saying that you have implemented this in a production system?  And if so, how do you keep the index in sync with the data when inserts/deletes occur?  Just wondering...

Thanks for the comments~!</description>
		<content:encoded><![CDATA[<p>@Marc Scheuner:</p>
<p>Yep, I completely respect Kim&#8217;s expertise when it comes to tuning SQLServer for performance and so I&#8217;m well-aware of what she&#8217;s suggesting here: that randomly-ordered PKs are awful in re: the performance of SQL Server indexing and I don&#8217;t dispute this point at all as all the literature would (and my own experience) would certainly back her up on this.</p>
<p>This is why I make use of the Guid.Comb generator for identity (PK) values in my NHibernate-based solutions.  Guid.Comb results in a unique yet also ever-increasing value for the identity which is what Kim is suggesting at the end of her post here&#8230;</p>
<p><a href="http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain" rel="nofollow">http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain</a>!.aspx</p>
<p>&#8230;in which she suggests that under SQL Server 2005 (and also SQL Server 2008, of course) one should choose the newsequentialid() method over the completely random newid() method in the database.</p>
<p>The Guid.Comb identity generator in NHibernate is essentially the non-database-dependent version of the SQL Server newsequentialid() function that can be invoked client-side without requiring a database round-trip just to get a new PK for an entity.</p>
<p>The idea of using a separate INT IDENTITY column in the DB along with the Guid as PK and having the clustered index depend on this INT value is an interesting one I hadn&#8217;t considered before &#8212; are you saying that you have implemented this in a production system?  And if so, how do you keep the index in sync with the data when inserts/deletes occur?  Just wondering&#8230;</p>
<p>Thanks for the comments~!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Marc Scheuner</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-16756</link>
		<dc:creator>Marc Scheuner</dc:creator>
		<pubDate>Mon, 08 Jun 2009 17:34:08 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-16756</guid>
		<description>For really detailed and profound background info on why a GUID is a TERRIBLE choice for a clustering key in SQL Server, check out the various articles by Kim Tripp - she's arguably one of the most prominent experts in SQL Server performance and index tuning there is.

http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx

http://sqlskills.com/BLOGS/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain!.aspx

If you really want to and have to use GUID's as PRIMARY KEY, you should always try to use a separate INT IDENTITY column to cluster the table. The performance differences are MASSIVE indeed (seen first hand with tables of 20'000 rows or more).

Marc</description>
		<content:encoded><![CDATA[<p>For really detailed and profound background info on why a GUID is a TERRIBLE choice for a clustering key in SQL Server, check out the various articles by Kim Tripp - she&#8217;s arguably one of the most prominent experts in SQL Server performance and index tuning there is.</p>
<p><a href="http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx" rel="nofollow">http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx</a></p>
<p><a href="http://sqlskills.com/BLOGS/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx" rel="nofollow">http://sqlskills.com/BLOGS/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx</a></p>
<p><a href="http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain" rel="nofollow">http://www.sqlskills.com/BLOGS/KIMBERLY/post/Ever-increasing-clustering-key-the-Clustered-Index-Debateagain</a>!.aspx</p>
<p>If you really want to and have to use GUID&#8217;s as PRIMARY KEY, you should always try to use a separate INT IDENTITY column to cluster the table. The performance differences are MASSIVE indeed (seen first hand with tables of 20&#8242;000 rows or more).</p>
<p>Marc</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sbohlen</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6810</link>
		<dc:creator>sbohlen</dc:creator>
		<pubDate>Sat, 27 Dec 2008 21:43:17 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6810</guid>
		<description>@Serial Nightmare:

The dictionary example is an interesting one I hadn't considered -- I will have to give that some more thought...

But the first situation is NEVER going to happen -- that's the point of the DDD concept of 'aggregate root'.  If the parent holds a collection of children, then that parent is going to be responsible for managing the lifecycle of its children.

If it were to 'give' a transient instance to another part of the app before assigning it an Id (by persisting it), then I think that's essentially relinquishing control of the item to the other aggregate root which (even if it were a good idea) would probably mean that the item would be REMOVED from the original parent rather than a copy of it given out to the other.  Then the responsibility for managing that child would also be passed to the second parent.  In essence, handing off a child from one parent to the next is also handing off lifecycle management for that child from one parent to the next.

I agree that its POSSIBLE that the first parent would relinquish a *copy* of one of its children to another part of the app, but I would also have to say that it seems to me to be a poor design decision to do so -- I would probably REMOVE the item from the first parent's collection of children and then ADD it to the second parent's collection rather than have Parent1 hand a copy to Parent2 (and create exactly the trouble you are quite correctly pointing out could easily occur).  This is just one of the reasons why I tend to shudder inside when I see props on objects that expose non-read-only collections (the members of that collection are suddenly completely exposed to the world).

I am inclined to concur with your paranoid estimation that this trouble is indeed possible, but to create these conditions would (I think) require me to go against all the rest of the tenets of DDD that I tend to consider good practice.  Hopefully, if a dev on the project did follow the pattern you are describing, the rest of the team would catch it in tests, code-reviews, etc., but I think you're quite right that it represents at least a potential point of contention to watch out for.

Thanks for the points~!</description>
		<content:encoded><![CDATA[<p>@Serial Nightmare:</p>
<p>The dictionary example is an interesting one I hadn&#8217;t considered &#8212; I will have to give that some more thought&#8230;</p>
<p>But the first situation is NEVER going to happen &#8212; that&#8217;s the point of the DDD concept of &#8216;aggregate root&#8217;.  If the parent holds a collection of children, then that parent is going to be responsible for managing the lifecycle of its children.</p>
<p>If it were to &#8216;give&#8217; a transient instance to another part of the app before assigning it an Id (by persisting it), then I think that&#8217;s essentially relinquishing control of the item to the other aggregate root which (even if it were a good idea) would probably mean that the item would be REMOVED from the original parent rather than a copy of it given out to the other.  Then the responsibility for managing that child would also be passed to the second parent.  In essence, handing off a child from one parent to the next is also handing off lifecycle management for that child from one parent to the next.</p>
<p>I agree that its POSSIBLE that the first parent would relinquish a *copy* of one of its children to another part of the app, but I would also have to say that it seems to me to be a poor design decision to do so &#8212; I would probably REMOVE the item from the first parent&#8217;s collection of children and then ADD it to the second parent&#8217;s collection rather than have Parent1 hand a copy to Parent2 (and create exactly the trouble you are quite correctly pointing out could easily occur).  This is just one of the reasons why I tend to shudder inside when I see props on objects that expose non-read-only collections (the members of that collection are suddenly completely exposed to the world).</p>
<p>I am inclined to concur with your paranoid estimation that this trouble is indeed possible, but to create these conditions would (I think) require me to go against all the rest of the tenets of DDD that I tend to consider good practice.  Hopefully, if a dev on the project did follow the pattern you are describing, the rest of the team would catch it in tests, code-reviews, etc., but I think you&#8217;re quite right that it represents at least a potential point of contention to watch out for.</p>
<p>Thanks for the points~!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Serial Nightmare</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6806</link>
		<dc:creator>Serial Nightmare</dc:creator>
		<pubDate>Sat, 27 Dec 2008 20:59:25 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6806</guid>
		<description>@sbohlen

For about 2 years I was working on a large legacy C/C++ codebase. I think that this experience might have made me "sensitive" (read: paranoid :) ) to such edge cases.

I can only imagine such scenarios where you have to code defensively in a not disciplined big ball of mud project. If your class is responsible for a list of objects that have to be different (different id) and someone would take one of the items already in the list and give it back to you as a new item you could not check if this object is already there or not.

Or if the Hash function is based on the Guid inside the Id you could run into problems if you want to put transient objects into a Dictionary. If two transient objects can not be equal you might not be able to use them as keys in a Dictionary.</description>
		<content:encoded><![CDATA[<p>@sbohlen</p>
<p>For about 2 years I was working on a large legacy C/C++ codebase. I think that this experience might have made me &#8220;sensitive&#8221; (read: paranoid <img src='http://unhandled-exceptions.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) to such edge cases.</p>
<p>I can only imagine such scenarios where you have to code defensively in a not disciplined big ball of mud project. If your class is responsible for a list of objects that have to be different (different id) and someone would take one of the items already in the list and give it back to you as a new item you could not check if this object is already there or not.</p>
<p>Or if the Hash function is based on the Guid inside the Id you could run into problems if you want to put transient objects into a Dictionary. If two transient objects can not be equal you might not be able to use them as keys in a Dictionary.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sbohlen</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6798</link>
		<dc:creator>sbohlen</dc:creator>
		<pubDate>Sat, 27 Dec 2008 15:51:50 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6798</guid>
		<description>@Serial Nightmare:

You are suggesting an interesting side-effect of my approach that I must confess to not having fully considered: that of an object not being equal to itself.  Can you demonstrate for me the (actual) case where this comparison would be useful/valuable in an actual app?  I haven't stumbled across such a case in my experience though that doesn't even come close to proving that there isn't one :D  Can you help me understand what use-case are you positing this would be a hinderance for...?

And, yes, the other reason for leaving the _persistenceId as its 'unassigned' default of Guid.Empty is indeed b/c that's part of how NHibernate considers whether its dealing with a persistent or transient instance.  This in turn leads to how it understands whether it needs to do a 'save' (an SQL INSERT statement) or an 'update' (an SQL UPDATE statement).

If we were to assign a Guid on entity construction, then WE would have to take over that responsibility ourselves as developers and ensure that we always invoked EITHER ISession.Save(...) or ISession.Update(...) as needed.  With my present implementation, we can near-always invoke ISession.SaveOrUpdate(...) and let the NHibernate framework decide for itself whether an INSERT or UPDATE statement needs to be generated (based on the value of the _persistenceId field in the base class).

This kind of thing is one of the reasons why (IMHO) persistence-ignorance (PI) of our domain entities is a GOAL rather than an absolute.  Using something like NHibernate, its actually the case that if 'pure' PI is what you want, there are enough extensibility points in the tool to allow you to achieve just that but if you back off from the 'purity' of PI just a bit, you can let the framework (NH in this case) do more of the heavy-lifting for you.  Designing your domain model so that NH can be given the right 'hints' about whether to construct and INSERT or an UPDATE statement when the session is flushed is just once such 'concession' to pure PI that I am willing to make in this kind of case.</description>
		<content:encoded><![CDATA[<p>@Serial Nightmare:</p>
<p>You are suggesting an interesting side-effect of my approach that I must confess to not having fully considered: that of an object not being equal to itself.  Can you demonstrate for me the (actual) case where this comparison would be useful/valuable in an actual app?  I haven&#8217;t stumbled across such a case in my experience though that doesn&#8217;t even come close to proving that there isn&#8217;t one <img src='http://unhandled-exceptions.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  Can you help me understand what use-case are you positing this would be a hinderance for&#8230;?</p>
<p>And, yes, the other reason for leaving the _persistenceId as its &#8216;unassigned&#8217; default of Guid.Empty is indeed b/c that&#8217;s part of how NHibernate considers whether its dealing with a persistent or transient instance.  This in turn leads to how it understands whether it needs to do a &#8217;save&#8217; (an SQL INSERT statement) or an &#8216;update&#8217; (an SQL UPDATE statement).</p>
<p>If we were to assign a Guid on entity construction, then WE would have to take over that responsibility ourselves as developers and ensure that we always invoked EITHER ISession.Save(&#8230;) or ISession.Update(&#8230;) as needed.  With my present implementation, we can near-always invoke ISession.SaveOrUpdate(&#8230;) and let the NHibernate framework decide for itself whether an INSERT or UPDATE statement needs to be generated (based on the value of the _persistenceId field in the base class).</p>
<p>This kind of thing is one of the reasons why (IMHO) persistence-ignorance (PI) of our domain entities is a GOAL rather than an absolute.  Using something like NHibernate, its actually the case that if &#8216;pure&#8217; PI is what you want, there are enough extensibility points in the tool to allow you to achieve just that but if you back off from the &#8216;purity&#8217; of PI just a bit, you can let the framework (NH in this case) do more of the heavy-lifting for you.  Designing your domain model so that NH can be given the right &#8216;hints&#8217; about whether to construct and INSERT or an UPDATE statement when the session is flushed is just once such &#8216;concession&#8217; to pure PI that I am willing to make in this kind of case.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Serial Nightmare</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6797</link>
		<dc:creator>Serial Nightmare</dc:creator>
		<pubDate>Sat, 27 Dec 2008 14:48:47 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6797</guid>
		<description>@sbohlen

I understand and agree that if the Id is equal that should mean that the two objects are equal no matter what the rest of their fields hold. If rest of the fields were different that would mean only that one of the objects was loaded at a different time then the other or it was changed after load. 
What I meant was that if an object is transient it would not be equal to itself.
ex. 
Employee emp = new Employee();
Assert(emp.Equals(emp)) // Fails
This would be solved if the Id would be assigned in the constructor.  
Could this be a problem, or are there some best practices to avoid this?
Do you have to do that because NHibernate compares the Id to the unsaved-value to see if the object was persisted or not? (I just saw that in your NHibernate screencast session 1)</description>
		<content:encoded><![CDATA[<p>@sbohlen</p>
<p>I understand and agree that if the Id is equal that should mean that the two objects are equal no matter what the rest of their fields hold. If rest of the fields were different that would mean only that one of the objects was loaded at a different time then the other or it was changed after load.<br />
What I meant was that if an object is transient it would not be equal to itself.<br />
ex.<br />
Employee emp = new Employee();<br />
Assert(emp.Equals(emp)) // Fails<br />
This would be solved if the Id would be assigned in the constructor.<br />
Could this be a problem, or are there some best practices to avoid this?<br />
Do you have to do that because NHibernate compares the Id to the unsaved-value to see if the object was persisted or not? (I just saw that in your NHibernate screencast session 1)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sbohlen</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6795</link>
		<dc:creator>sbohlen</dc:creator>
		<pubDate>Sat, 27 Dec 2008 12:49:18 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6795</guid>
		<description>@Serial Nightmare:

Thanks for the great question: here's the summary of why I chose the equality behavior as I did...

I agree with you that it might seem counter-intuitive for a novice user; that's one of the reasons that I pointed out in the screencasts that it works the way it does -- I may not have been as explicit I could have been as to WHY I chose to make it work this way tho...

The single underlying principle behind my implementation of equality in the base class is "identity is based solely on the value of the identity field and nothing else".  This is (if you think about it) the same thing that happens in just about any DB...if two rows have the same primary key, they are considered THE SAME ROW.  If two rows have different PK values, they are considered NOT THE SAME ROW no matter the values of their constituent fields.

I can see how 'expecting' value equality (the default where if each public field is equal, then the two instances of the object are considered equal) would seem intuitive if the entity wasn't yet persisted but this would introduce two completely different evaluations of equality for persisted and transient (non-persisted) entities and this would (IMHO) introduce MORE chances for bugs rather than less.

re: assigning the identity value in the constructor, as I see it this doesn't seem to buy me anything I don't already have with my present implementation.  If I leave the _persitenceId value as Guid.Empty and say (as I do) that the comparison of two Guid.Empty values is non-equal, then isn't this the same thing I would get if I assigned the identity value in the constructor --?  Two non-persisted entities would still have (I assume) different Guids assigned to them and they would still equate to non-equal (since their Guids would be non-equal).  I may be misunderstanding your suggestion, can you clarify if I'm not getting it...?

Basically what it comes down to is this: I want identity (and by extension, the notion of equality) in my object model to be based on the same rules as my persistence environment (the DB) so that I can never end up with two persistent entities equal as objects but non-equal in the database.  Since equality in the DB is purely a function of the PK values, then I want the same 'rules' in my domain model and this is what I was shooting for with the persistence base class and the implementation of the equality operator that's in there.

Does this make sense...?</description>
		<content:encoded><![CDATA[<p>@Serial Nightmare:</p>
<p>Thanks for the great question: here&#8217;s the summary of why I chose the equality behavior as I did&#8230;</p>
<p>I agree with you that it might seem counter-intuitive for a novice user; that&#8217;s one of the reasons that I pointed out in the screencasts that it works the way it does &#8212; I may not have been as explicit I could have been as to WHY I chose to make it work this way tho&#8230;</p>
<p>The single underlying principle behind my implementation of equality in the base class is &#8220;identity is based solely on the value of the identity field and nothing else&#8221;.  This is (if you think about it) the same thing that happens in just about any DB&#8230;if two rows have the same primary key, they are considered THE SAME ROW.  If two rows have different PK values, they are considered NOT THE SAME ROW no matter the values of their constituent fields.</p>
<p>I can see how &#8216;expecting&#8217; value equality (the default where if each public field is equal, then the two instances of the object are considered equal) would seem intuitive if the entity wasn&#8217;t yet persisted but this would introduce two completely different evaluations of equality for persisted and transient (non-persisted) entities and this would (IMHO) introduce MORE chances for bugs rather than less.</p>
<p>re: assigning the identity value in the constructor, as I see it this doesn&#8217;t seem to buy me anything I don&#8217;t already have with my present implementation.  If I leave the _persitenceId value as Guid.Empty and say (as I do) that the comparison of two Guid.Empty values is non-equal, then isn&#8217;t this the same thing I would get if I assigned the identity value in the constructor &#8211;?  Two non-persisted entities would still have (I assume) different Guids assigned to them and they would still equate to non-equal (since their Guids would be non-equal).  I may be misunderstanding your suggestion, can you clarify if I&#8217;m not getting it&#8230;?</p>
<p>Basically what it comes down to is this: I want identity (and by extension, the notion of equality) in my object model to be based on the same rules as my persistence environment (the DB) so that I can never end up with two persistent entities equal as objects but non-equal in the database.  Since equality in the DB is purely a function of the PK values, then I want the same &#8216;rules&#8217; in my domain model and this is what I was shooting for with the persistence base class and the implementation of the equality operator that&#8217;s in there.</p>
<p>Does this make sense&#8230;?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Serial Nightmare</title>
		<link>http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/comment-page-1/#comment-6792</link>
		<dc:creator>Serial Nightmare</dc:creator>
		<pubDate>Sat, 27 Dec 2008 11:17:36 +0000</pubDate>
		<guid isPermaLink="false">http://unhandled-exceptions.com/blog/index.php/2008/12/11/on-choosing-an-identity-type/#comment-6792</guid>
		<description>Hi,

I was wondering why you choose in GuidIdentityPersistenceBase Eqaul to treat all objects with a _persistencId of 0 as not comparable. If a object was not persisted yet wouldn't it be better if you use the reference equal in this case or generate a guid when the constructor is called? In my opinion this behavior is not intuitive for a novice user and could introduce subtle bugs if the coder is new to your practices.
I'm new the NHibernate and the Rhino IoC stuff so I'm sure that I am missing something. Could you please explain this design decision?</description>
		<content:encoded><![CDATA[<p>Hi,</p>
<p>I was wondering why you choose in GuidIdentityPersistenceBase Eqaul to treat all objects with a _persistencId of 0 as not comparable. If a object was not persisted yet wouldn&#8217;t it be better if you use the reference equal in this case or generate a guid when the constructor is called? In my opinion this behavior is not intuitive for a novice user and could introduce subtle bugs if the coder is new to your practices.<br />
I&#8217;m new the NHibernate and the Rhino IoC stuff so I&#8217;m sure that I am missing something. Could you please explain this design decision?</p>
]]></content:encoded>
	</item>
</channel>
</rss>

