views:

107

answers:

2

Hi!

After I retrieve an entity, I change a property of it. Then I retrieve the same entity.

How do I say Nhibernate, that it shall update the entity before it loads the entity?

Here the code:

EmployeeRepository employeeRepository = new EmployeeRepository();
Employee employee = employeeRepository.GetById(4);
employee.LastName = "TEST!!!";
Employee employee2 = employeeRepository.GetById(4);

Currently Nhibernate don't make an update in my program. I thought just setting the FlushMode to Auto will update the entity automatically.

EDIT The background is that I try to reprdouce this behaviour in another application. There is NO save method! Just this code. The NHibernate version is really old, it is version 1.2.1.4000. maybe there is the catch.

When I set the FlushMode in the brownfield application to Commit then no update statement is generated.

But in my own project I still can not reproduce this "automatic" behaviour.

+3  A: 

Are both calls to the employeeRepository ultimately using the same NHibernate ISession instance? If so, then they will return the same object, and the updated LastName value will be reflected. If not, then you will need to make sure you are disposing your ISession instance each time to take advantage of auto flushing.

David M
please look at my editing
Rookian
so when I use the same "ISeesions" NHibernate will automatically call an update sql statement, because I have the FlushMode set to auto?
Rookian
No, it will cache the changed object in memory.
David M
I used the debugger in visual studio ("make object id" i.e. #1) to test if the repository is using the same ISession and they do. BUT an update statement is generated by NHibernate. I can't understand this.
Rookian
In my own solution it works as you described. There is first no 2nd select statement created and an update statement is also not created by NHibernate. But in another brownfield application there is still generated and executed an update and select statement.
Rookian
the value reflection is used whether you use Get, Load, or the ICriteriAPI, cool stuff ;) All 3 techniques don't generate the update statement :/
Rookian
+1  A: 

According to the documentation for the default FlushMode of Auto:

The ISession is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.

So you have to manually flush the session to ensure that your changes are persisted before reading the object again.

EmployeeRepository employeeRepository = new EmployeeRepository();
Employee employee = employeeRepository.GetById(4);
employee.LastName = "TEST!!!";
session.Flush();
Employee employee2 = employeeRepository.GetById(4);

If your repository is using the same ISession for both calls (as it should imo) then employee 4 will be retrieved from the cache and have the change. However, the change will not have been persisted to the database yet.

If your repository GetById methods uses a new session for each call then it will always hit the database to retrieve the employee. If you're disposing of the session in the method then your objects are returned as detached from a session. This strategy defeats the purpose of NHibernate and relegates it to a simple data access tool.

Jamie Ide
"The ISession is sometimes flushed" What means sometimes :D? Well, when Nhibernate is calling an update sql statement? I did not understand this correctly.
Rookian
I don't know with any certainty. My expectation is that if you retrieved and altered an employee then did a select on the table, NHibernate would flush the session first so that the query would return consistent results. This can only work if the operations are done in the same session. Getting an object by primary key is a different story; in this case NHibernate will retrieve it from cache.
Jamie Ide
I now retrieved the entity via the ICriteria API by implementing a GetByName method, but there is still no update statement. I have the same session, FlushMode = auto. What do I wrong?
Rookian
You are doing nothing wrong. This is the expected and documented behavior. You must flush the session to persist changes to the database.
Jamie Ide
But in my brownfield application I do not have to flush the session by hand. There is a magically update statement created and I can not reproduce this.
Rookian
Your other application is flushing the session, committing a transaction, or NHibernate has auto flushed the session. Without seeing the code for both applications it's hard to say. It is possible that the logic for auto-flushing has changed between versions. Regardless, you should never rely on NHibernate to persist your changes without a flush or commit.
Jamie Ide
in the brownfield application there is only the usage of the ICriteria API. I debugged the application step by step. I just wanted to understand when Nhibernate creates and executes an update statement and when not. For now, I know that there has to be the same ISession and FlusMode has to be set to Auto. The rest is magic :o But I am still interessted in more details :)
Rookian
See my answer to this question: http://stackoverflow.com/questions/3295169/nhibernate-flushmode-auto-not-flushing-before-find/3295643#3295643
Jamie Ide