I'm having trouble implementing optimisitc concurrency in NHibernate in a meaningful way in a web application. Here is the desired scenario:
- User A opens a form to edit a record
- User B opens the same form to edit the same record
- User A saves their data
- User B tries to save their data but get a warning that the data has been updated.
A common scenario. Here is the update code and entity mapping file:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Entities" assembly="Domain">
<class name="Record" />
<id name="Id" column="Id" type="long">
<generator class="identity"/>
</id>
<version name="Version" column="Version" type="datetime" />
<property name="Description" column="`Description`" type="string" />
</class>
</hibernate-mapping>
public void Edit(int id, string description, DateTime version)
{
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var record = session.Get<Record>(id);
record.Version = version;
record.Description = description;
session.Update(record);
tx.Commit();
}
}
The version value is loaded when the user opens the form and is stored in a hidden field. I was hoping NHibernate would try to update with the version from the form in the WHERE clause, but instead it uses the value it has just loaded in the session.
Other things I have read tell me that I should manuall compare values, and (for example) throw an exception if it loads a newer version. But I can't believe there is a better way.
It seems to me that NHibernate's concurrency controls are only useful in the same session, and therefore completely useless when it comes to stale form data on web based applications.
I want to be able to manually set the version based on what was in the form when the user originally loaded it. Is this possible? Or am I missing something here?