tags:

views:

48

answers:

3

If I call Save on a new object, then populate its properties, NHibernate generates and insert statement that contains only the default values for the properties. For example (session is an open ISession):

var homer = new Person();
session.Save(homer);
homer.Name = "Homer J. Simpson";
session.Flush();

I thought that calling Save would make homer persistent and that NH would track any changes and include them in the insert. Instead, it issues an insert with the name property parameter set to null. If I put the Save call after the assignment then it works. This object has a GUID id assigned by NH so it's not doing a premature insert to get an identity.

ETA I'm using session-per-request in an ASP.NET app and the pattern I want to follow is:

MyObject myObject;
if (id == null)
{
    myObject = new MyObject();
    repository.Add(myObject);
}
else
{
    myObject = repository.GetMyObject(id);
}
// populate myObject's properties
// NH magic happens here when the HTTP request ends
+2  A: 

I think your assumption in this case is simply incorrect.

Reading the code sample you provided, you could just as well expect NHibernate to insert the object, and then subsequently change the Name and then issue an Update. That, however, would assume that Flush implicitly saves the changed state.

Joseph
Actually, the scenario you gave is probably what is happening. NH wants to do an insert with the object state at the time I called Save then issue an update for state changes made since then. But it never gets to the second step because the insert fails due to not null constraint violations in the database.
Jamie Ide
+1  A: 

I also wonder why this happens. NH should really wait to insert the object to the database.

Reasons why could do this:

  • the id, you already said that you are using guids, so this shouldn't be the reason.
  • there is a query. To ensure that it is performed on actual data, the session is flushed.
  • there are calculated columns, which need to be read back from the database
  • there might be other reasons I don't remember.

Is this really the code you are running to reproduce the test?

How does the mapping file look like?

Stefan Steinegger
This is not the real code, but your bullet points 1 and 3 do not apply. I will try to put together a better example but this is a very simple case. It's an anemic domain model and the class has no relationships, just properties.
Jamie Ide
A: 

You just mentioned it in the answer to my (perhaps rather naive) comment. You have set session FlushMode to Auto. Change that to Manual and you're more likely to see the behavior you are seeking.

It's still a rather wild guess, simply because so many other properties of your configuration can be at play.

Abel