views:

408

answers:

4

I have a object with a Nhibernate mapping that has a surrogate ID and a natual ID. Since of cource the natural ID is uniquely constrained a insert query will fail if the object is already in the database with the same natural ID. My solution for this has been to manually check to see if natural IDs are in the database before trying to insert.

Is there a way to specify Nhibernate to do a select before insert on natural Id's/Unique Constraints?

A: 

In one way or another, you'll have to go to the DB.

However, you can do it in a more transparent way with NH Validator.

Read the following post from Fabio Maulo: http://fabiomaulo.blogspot.com/2009/10/validation-through-persistence-not.html

Diego Mijelshon
How do validators help me?
Will
A: 

I usually solve that kind of scenario by just trying to insert (submitting the changes) and catching the resulting exception.

You'll have to hit the DB anyway, so a failing INSERT has basically the same cost (if not cheaper) than a SELECT... And it's safer.

Fábio Batista
The problem comes from when these objects are part of a cascaded construct. The single object that I really don't care about if it updates or inserts breaks the transaction for the entire construct.
Will
A: 

I check for uniqueness before save or update. Then I can display a nice validation message. I've found it difficult to read the exception and match the constraint violation to the correct field. Maybe NH has abstracted the error codes for supported databases...I haven't looked into that. In the rare case the constraint gets violated between the check and save, user gets a general error message.

dotjoe
A: 

I ended up building a SaveOrUpdate listener for Nhibernate so as objects are about to be saved to the database I can determine if their uniqueness should be checked. Instead of just selecting to see if the object unique properties exist in the database I do a select for update (pessimistic lock) so the row will be locked so I can safely merge and update the object. The does create O(2N) queries but if it becomes a problem I could simplify it into a single merge statement.

http://en.wikipedia.org/wiki/Merge_(SQL)

Will