Sorry, just noticed a typo in the code from the email.  Corrected it and
re-sent.

 

Remi.

 

From: Rémi Després-Smyth [mailto:[email protected]] 
Sent: November 20, 2009 3:17 PM
To: [email protected]
Subject: [nhusers] how should optimistic concurrency using a version field
work?

 

Can anyone explain optimistic locking in the context of NHibernate?  (Using
NHib 2.1.1.)

 

I’ve been running tests and my results are counter-intuitive.  I have a
versioned entity: 

 

 

<class name="Test.Entity, Test" table="tblEntity" abstract="false"
optimistic-lock="version">

 

      <id name="Id" column="scheduleId" access="property" unsaved-value="0"
type="Int64">

            <generator class="hilo">

                  <param name="table">tblHiloUId</param>

                  <param name="column">nextHighValue</param>

                  <param name="max_lo">100</param>

            </generator>

      </id>

 

      <version column="version" name="Version" type="Int32"
unsaved-value="0" />

 

      <property name="Prop1" column="prop1" update="false"

            access="property" not-null="false" type="Boolean"

            optimistic-lock="true" />

 

      <property name="Prop2" column="isDefaultOverridable"

            access="field" not-null="true" type="String" 

optimistic-lock="true" />

</class>

 

And the following test: 

 

[Test, ExpectedException(ExceptionType=typeof(StaleObjectStateException))]

public void SavingUpdatesOptimisticLockShouldThrow()

{

      var cfg = new NHibernate.Cfg.Configuration();

      cfg.AddAssembly("Test");

      cfg.Configure();

      var sessionFactory = cfg.BuildSessionFactory();

 

      var sess1 = sessionFactory.OpenSession();

      var sess2 = sessionFactory.OpenSession();

 

      sess1.BeginTransaction();

      sess2.BeginTransaction();

 

      // NOTE: I get the same results if I load with Lock.None

// A record is loaded in the DB in test setup, assigned to m_Id

      var a = sess1.Load<Entity>(m_Id);

      var b = sess2.Load<Entity>(m_Id);

 

      a.Prop2 = "New test value, session1”;

      sess1.Save(a);

      sess1.Transaction.Commit();

 

      b.Prop2 = "Another, session2";

      sess2.Save(b);

      sess2.Transaction.Commit();   // Should throw?

}

 

After reading the docs, this is what I’d expect to see:

 

Both instances start with version=1.  When I save and commit a, I see that
its version number is incremented from 1 to 2, while b still has version=1
(as I’d expect).  I’d expect that the call to sess2.Transaction.Commit()
should throw, because NHibernate will determine that the record was updated
since b was loaded, so optimistic concurrency issue.  But it doesn’t – b
commits fine, and overwrites changes saved when a was saved.

 

If I load explicitly selecting the lock I want, it does work as I’d expect
and I get my exception.

 

This is surprising to me.  Ayende noted in a concurrency blog post
(http://ayende.com/Blog/archive/2009/04/15/nhibernate-mapping-concurrency.as
px) that using a version column should result in the generated UPDATE SQL
statement to compare against the version number – and if the version doesn’t
match the original version, we should get a StaleObjectException.

 

Can anyone clarify what’s going on here?

 

Thanks.

Remi.

 

--

You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=.

--

You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=.


Reply via email to