When is the save actually done?

1 view
Skip to first unread message

Berke

unread,
Oct 27, 2008, 2:12:16 PM10/27/08
to nhusers
I'm know this is a very basic question and for that I applogize but I
am missing something fundamental here. I am using an open session in
view model, and I close the session in the EndRequest event of an
httpmodule.

I just noticed that when I called SaveOrUpdate on my root object that
is was not actually saved to the DB until I closed the session. I
would like for the object to be persisted when I call into nHibernate
allowing me to handle failures gracefuly.

I am using the following snippet to map this object:

<class name="xxx.Organization" table="Organization" lazy="false">
<id name="Id" column="OrganizationId">
<generator class="guid" />
</id>
<property name="Name" column="Name" type="String" length="50"/>

.... other properties removed, I do have Components, an IdBag and a
Set in addition to regular properties.
</class>

I guess my workaround is to force a flush after I call SaveOrUpdate
but what is the recommended practice? Am I missing something else?

Thanks guys,
Josh

Symon Rottem

unread,
Oct 27, 2008, 2:34:30 PM10/27/08
to nhu...@googlegroups.com
Newly persistent and modified entities are flushed depending on the FlushMode that's set - the default is to flush on commit or when a query is executed (to make sure the query results reflect the in-memory changes).

If you were using database assigned identifiers the newly persistent objects would be flushed to the DB as soon as they're saved to get their Ids.

Cheers,

Symon.
--
Symon Rottem
http://blog.symbiotic-development.com

Berke

unread,
Oct 27, 2008, 2:38:02 PM10/27/08
to nhusers
Ok, some more thoughts here, so when I forced a call to Flush after
the SaveOrUpdate method, I noticed the behavior was still the same
that during the EndRequest handler I was still trying to save this
object. So what I am assuming is that when nHibernate encounters an
error while trying to save an object that it doesn't remove the object
from its list of dirty objects. So when my handler executes (Which
calls Flush and then Close()), nHibernate tries to save this object
again, but encounters the same error, resulting in an unhandled
exception.

Just to verify I removed all the calls to Flush & Close to see if the
object would be saved when calling SaveOrUpdate() and I noticed it was
not. My object was originally loaded up as property on another object
(many-one relationship), it's mapped as follows:

<class name="xxx.User" table="[User]" lazy="false">

<many-to-one name="Organization" class="xxx.Organization" not-
null="false" insert="true" update="true" cascade="save-update"
fetch="join" >
<column name="OrganizationId"/>
</many-to-one>
</class>

When I call the SaveOrUpdate method, I am passing the Organization
object not the user object.

This has raised a second question, do people usually flush when
closing the session in the open session in view pattern and if so how
do you handle reporting to the user in a graceful manner that an error
occured.

Tuna Toksöz

unread,
Oct 27, 2008, 2:49:02 PM10/27/08
to nhu...@googlegroups.com
or when a query is executed (to make sure the query results reflect the in-memory changes).

Partially correct, the consept QuerySpaces comes in to play. If a query wants items from EntityA and queries the property of type EntityB then only if there are instances of EntityA and EntityB in the dirty list, then flush will occur
--
Tuna Toksöz

Typos included to enhance the readers attention!

Gustavo Ringel

unread,
Oct 27, 2008, 2:49:24 PM10/27/08
to nhu...@googlegroups.com
A common case is using flushMode = commit so you get flushes when commiting transactions.
It's uncommon to see people calling session.Flush manually...

There may be other strategies depending on the use cases, but flushMode = commit is a nice one.

Gustavo.

Berke

unread,
Oct 27, 2008, 3:09:37 PM10/27/08
to nhusers
And this makes sense to me, if I was using transactions right now,
I've not explicitly setup a transaction, so I would assume the
behavior would be to persist the update when I call SaveOrUpdate,
(sort of like an implicit transaction that my entire save should
commit or roll back).

Josh

Gustavo Ringel

unread,
Oct 27, 2008, 3:14:22 PM10/27/08
to nhu...@googlegroups.com
SaveOrUpdate has nothing to do with DB, it tells NHibernate to register the entity as a persistent entity and it puts it in the 1st level cache.
You should never expect as a rule to hit the DB while saving/updating or deleting. You will get a hit or not depending on a lot of considerations...

Gustavo.

Gustavo Ringel

unread,
Oct 27, 2008, 3:18:03 PM10/27/08
to nhu...@googlegroups.com
Ah and from NH2.0 there is no AutoFlush outside a Transaction, you should work with transactions if you are using NH2.0 and in general...you should work with transactions.
An RDBMS is a transaction engine...if you don't manage them the RDBMS will manage the transactions...and that's not what you want in general.
For example in SQL Server it will auto commit every sql you sent...you want to commit every time or you want to commit when you made all the work in your current use case, having the option to rollback?

Gustavo.

Berke

unread,
Oct 27, 2008, 4:13:31 PM10/27/08
to nhusers
That all depends on the use case, and the requirements but yes in
General I agree this should exist in a transaction and I am not sure
why I've not done this. So now where to control the transaction, I
like how right now my web has no concept of the data (outside of the
httpmodule that ensures the session is closed). It just takes a high
level "Service" which then uses a dao to perform the nHibernate
functionality. I'd hate to make the assumption that my Service
controls the transaction...since you might want to have two services
cordinated in a single transaction.

I'm struggling with finding a good pattern here that controls
transactions at the appropiate level, without leaking nHibernate to my
web...any thoughts?

Will Shaver

unread,
Oct 27, 2008, 4:23:54 PM10/27/08
to nhu...@googlegroups.com
What platform for web are you using?

I'd look into ATM

http://www.castleproject.org/container/facilities/trunk/atm/index.html

There are plenty of discussions about it in this group if you search
the archives.

Gustavo Ringel

unread,
Oct 27, 2008, 4:37:04 PM10/27/08
to nhu...@googlegroups.com
you should take a look on MVC frameworks like Monorail or ASP.NET MVC the controller should initiate the transactions IMHO.

Gustavo.

Berke

unread,
Oct 27, 2008, 5:28:05 PM10/27/08
to nhusers
I've been more and more tempted to look into Asp.Net MVC, the web is
getting difficult to manage as it grows, and sounds like the MVC
pattern might be able to help tame the beast so to say. I like the
idea of the control handling the transaction. This way the ultimate
consumer has the ability to bring together my services in whichever
way they need them to achieve their business requirements.

When you say which web platform I assume you mean asp.net web forms,
with .net 3.5.

In the mean time until I'm able to dive into MVC or Castle, I've ended
up creating my own little ISession like definition which gives me
ability to manage transactions, and using seperated interfaces I've
kept the implementation away from my web and my business layer, now I
just need a better IoC and we will almost be there.

Thanks for the help and ideas

Josh
Reply all
Reply to author
Forward
0 new messages