0
votes

I am dealing with concurrency issues in nhibernate and I am not really sure if I am doing right. I use a version field and when the transaction gets comitted, I think an StaleObjectStateException will get thrown if the version field was changed by another process. I catch this exception and handle that case and it seems to work.

But what I am wondering about is, that every time the exception is thrown, NHibernate produces an ERROR in my log4net-Logfile. I have set the loglevel for NHibernate to ERROR because I think that if an error occurs that should interest me. But I am not interested in all the messages about some concurrency conflict, because I don't regard that as an ERROR.

So it might be that I am doing something completely wrong? Is it the right way to deal with concurrency by catching the exception?

update: this is what nhibernate puts in my logfile:

2012-06-21 16:47:30,546 ERROR NHibernate.Event.Default.AbstractFlushingEventListener: Could not synchronize database state with session
NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Delta.FollowUp.Model.CFollowUp#60003]
   bei NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:Zeile 2780.
   bei NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:Zeile 2692.
   bei NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:Zeile 3000.
   bei NHibernate.Action.EntityUpdateAction.Execute() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Action\EntityUpdateAction.cs:Zeile 79.
   bei NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:Zeile 136.
   bei NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:Zeile 126.
   bei NHibernate.Engine.ActionQueue.ExecuteActions() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:Zeile 170.
   bei NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:Zeile 241.
2

2 Answers

1
votes

If you don't want to log NHibernate errors, just remove the logger for NHibernate, set it at the FATAL level, or filter the exceptions somehow.

You can still catch the exception, handle it, rethrow it, log it, whatever.

1
votes

What you do when there's a concurrency issue depends on the app. In a lot of cases it is sufficient to catch the exception and retry the unit of work - but defining the unit of work is where it can get tricky. Depending on your situation, it might be sufficient to load the entity again and make the changes again and then save it, but that really depends on your application.

Basically that exception means that another thread/process has changed the entity in the database, so you need to now react accordingly. NHibernate is logging it as an error because the use of a version field implies optimistic concurrency where you are assuming that nothing else is going to change the row(s) you're changing, so if something does change one of those rows then you need to handle it.