Thanks Socratees.
It does work with the lock mode explicitly specified – I’ve tried that. In the NHib docs, they refer to this (loading with an explicit lock mode) as pessimistic locking (http://nhforge.org/doc/nh/en/index.html#transactions-optimistic, section 10.6). However, the behavior I’m seeing when specifying the lock mode looks like optimistic locking to me (as described in section 10.4). That is: grab the record, assume that you can edit it, and when it’s time to save, check the version – if it was updated by someone else, throw an exception due to conflict. In my test below: · If I load the instances specifying a lock mode myself (the NHib docs call “pessimistic locking”), it looks to me like it’s doing optimistic locking; · If I don’t specify the lock mode when loading the isntances (which NHib calls “optimistic locking”), it looks to me like it isn’t doing anything at all. I assume that I don’t have a proper understanding of locking in this context, and I was hoping that someone could clarify it for me. Remi. From: Socratees Samipillai [mailto:[email protected]] Sent: November 20, 2009 4:16 PM To: [email protected] Subject: Re: [nhusers] how should optimistic concurrency using a version field work? [fixed typo] Hi Remi, I'm not an expert, but your updates might be taking place successfully because of the way you're loading the object. Session.Load<Entity>(Id) by default doesn't use any locks. It loads objects in an unlocked mode. Can you try Session.Load<Entity>(Id, LockMode) with Lockmode explicitly specified? Hope that solves your problem. Thanks, Socratees. 2009/11/20 Rémi Després-Smyth <[email protected]> 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] <mailto:nhusers%[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] <mailto:nhusers%[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=. -- 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=.
