views:

55

answers:

2

Is there a way to have NHibernate only update the fields that don't have the default value filled in? Say we have this simple class:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

We also have a standard NHibernate mapping using properties for each field and Id for the Id field.

Say we want a page to just update the Name, so we send down the Id, store it in a hidden field, and show a text box for the name. The user modifies the name and hits save. We POST back, new up a Person object, and assign the incoming Id and Name. We then tell NHibernate to update the database.

Problem is, the Age obviously gets set back to 0 in the database as it wasn't filled in coming back from the POST. The most obvious way around this is to send the Age value to the page, store it in a hidden field, and fill it back in before saving. That works fine until you get quite a few more properties on your object and only want to modify a hand full of them on the screen (or a large list of Person objects, which might require storing lots of values in hidden fields).

So back to the subject of the question: is there a way to tell NHibernate to basically ignore the Age property since it'd have a default value (0) before being updated, or am I stuck with a metric ton of hidden fields to keep the existing values?

A: 

This sounds a little suspicious. Normally, when you go to edit a Hibernate entity, you first load it from the database, make changes to it, then save it back to the database. You wouldn't normally create a new object, set its ID and whatever arbitrary properties, then save the new object, because, as you say, any properties that are not set will most likely be set to defaults.

By loading it from the database, all the properties are filled in appropriately, so you don't have to worry about maintaining the state of these yourself. The Hibernate session is responsible for maintaining the state of these objects until you save and flush them to the database.

There are different strategies for dealing with the hibernate session across web requests. Check out this article: http://hibernatebp.blogspot.com/ - look at session management strategies. "Session per request with detached objects" might be good in your case.

Andy White
Yes, I can load the Person, set the name, and save it. However, this is for a larger list of such objects, so I either do a load per object or get them all and do a lookup from the in memory collection to find the correct entity to update myself. Either way is a pain (though doable).I was wondering if there was an easier way.
Darrell Mozingo
+1  A: 

In the post back, Retrieve the persisted entity from the repository with the Id and update just the Name and persist it. This way, you don't need to maintain the values in hidden field.

Sathish Naga
In this contrived example, there's already an Age in the database and it can't be null. I just don't want NHibernate to overwrite the existing value on update.
Darrell Mozingo
Check the updated answer
Sathish Naga
See the other answer (http://stackoverflow.com/questions/831527/only-updating-filled-in-properties/831579#831579). I know I can do that, but if I have a large collection of objects to do it for, I was trying to avoid that or loading them all at once and then modifying the collection. Looks like those are the only two options though.
Darrell Mozingo
You could enable lazy load. So that you load only required collections.Another not a good approach is make your entities serializeable, put it in Session or ViewState. In Post back, update the entity and persist.
Sathish Naga
Satish has it right. This is just how ActiveRecord's ARDataBind does it: http://www.castleproject.org/monorail/documentation/trunk/integration/ar.html
Mauricio Scheffer