We are trying to combine objects after a StaleObjectStateException has been thrown to save a merged copy.
Here's our environmental situation:
Use case:
We want to gracefully handle the exception. Because the users share ownership of the parent, User 1 should be able to save successfully, and save the Parent with both his new child, and User 2's child.
When SOSE is thrown, according to Ayende (http://msdn.microsoft.com/en-us/magazine/ee819139.aspx):
your session and its loaded entities are toast, because with NHibernate, an exception thrown from a session moves that session into an undefined state. You can no longer use that session or any loaded entities
C1 has already been assigned an ID and Version # by the now-not-useful session. (I wish it had not been.)
How do we combine the use of ISession.Merge() and ISession.Refresh() to get a newly saved Parent that has both C1 and C2 ?
We have tried a number of arcane permutations, none of which fully work. Usually, either a "row was updated or deleted by another transaction (or unsaved-value mapping was incorrect" or an actual ID collision at the ODBC level.
Our theory, at the moment:
However, all the documentation suggests that newSession.Merge is supposed to be sufficient.
Other posts used as research:
Fluent NHibernate Newbie: Row was updated or deleted by another transaction
Is there an alternative to ISession.Merge() that doesn't throw when using optimistic locking?
StaleObjectstateException row was updated or deleted by
How I can tell NHibernate to save only changed properties
Hibernate (JPA): how to handle StaleObjectStateException when several object has been modified and commited (java, but relevant, i think)
Because the users share ownership of the parent, User 1 should be able to save successfully, and save the Parent with both his new child, and User 2's child.
Why don't you just disable optimistic locking on the child collection? Then anyone can add childs and it won't increase the version of the parent.
Otherwise, here is the solution my current project uses for all recoverable exceptions a session could throw (e.g. connection to DB lost, foreign key violated, ...):
session.Flush()
the session is serialized to a MemoryStream
.session.Flush()
or transaction.Commit()
throws an exception that is recoverable, the original session is disposed and the saved one is deserialized.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With