English 中文(简体)
Nhibernate, multithreading, and race condition
原标题:

I am having a problem with a race condition when saving to the database asynchronously using NHibernate. First an insert to the database is done asynchronously where the unique id is auto-generated. Before this insert returns back to the main thread with now persisted object that has the unique database generated id, the object in updated in some way. The update will fail if I call session.Update because the object to be updated does not have a an id value yet. If I call SaveOrUpdate it will obviously result in an insert instead of an Update because the id field of my entity is equal to the unsaved-value property. Hopefully this code makes the situation more clear:

Entity entity = new Entity()
//update some fields
entity.PropertyTwo = "new value";
//dataObject as the database auto-generated Id
//insert new row asynchronously in different thread
Entity entity.Id = dao.save(entity.Clone()).Id

//before the the entity is returned from the database, the entity might be updated
entity.Property =  new value ;
//entity might be sent without an Id since the first asynch call has not returned yet.
//update asynchronously in another thread
Object dataObject = dao.Update(entity); //fails because Id is not set yet

One solution is to generate the unique id in the code prior to saving. In this case the application manages the incrementing of the unique id as opposed to the database. Any other ways of handling this?

问题回答

Looks like you could be creating multiple threads in a single NHibernate Session. Sessions in NHibernate are not thread safe. You should never access the same Session in two concurrent threads. Try creating a separate session in your new thread and see if it resolves your problem.

Check out the NHibernate documentation section 10.2.

You need to put some kind of "Wait for the insert to finish" type logic before you call update. This is standard multi-threaded async programming.

It s very possible to call Insert and Update at the same time on the same object in a multi-threaded environment. You just need to make sure the underlying code is smart enough to:

  1. Do the insert before the update
  2. Wait for the insert to complete before starting the update

There are many different ways to do this and none of them are necessarily better than another. You conceptually need a lock that you can acquire, discard, and wait on.

Also, this problem doesn t really have anything to do with NHibernate. Multithreaded programming is very difficult. It s best to avoid multiple threads if at all possible as complexity can easily spiral out of control.





相关问题
Silverlight, Updating the UI during processing

I have a simple silverlight multifile upload application, and i want to provide the user with some feedback, right now its only in a test phase and i dont have the webservice. Somehow i cant get the ...

Is reading from an XmlDocument object thread safe?

I was wondering if i could safely read from an XmlDocument object using SelectNodes() and SelectSingleNode() from multiple threads with no problems. MSDN says that they are not guaranteed to be ...

Terminating a thread gracefully not using TerminateThread()

My application creates a thread and that runs in the background all the time. I can only terminate the thread manually, not from within the thread callback function. At the moment I am using ...

热门标签