The proxy does not actually contain any of your data after the Load. Not until you actually access its properties. When it's finally loaded it would already see the changes committed in the other transaction, and so there is no conflict. You should get a conflict error if you keep using Load(), but alter the order to modify b.Prop2 before commit the transaction that has loaded a.
Consider what could happen in web scenario: Client 1 submits a form, that uses Load() to get a proxy. Client 2 access the same form, which uses Load() to get a proxy. Client 1's page request access the object (causing data to be fetched from DB), modifies it and commits. Client 2's page request begin rendering by accessing a property of the object, causing the load. This now already sees the values as commited by client 1. Important thing to consider: If you design your page to load the object, render to form, send form to client, user edits, submit form, you load object again and begin update it, then YOU need to verify that the object you load the second time is the same version as when you first displayed the form to the client. NHibernate cannot help you with that. /Oskar 2009/11/23 Rémi Després-Smyth <[email protected]>: > Sorry, yes, I see in the docs that Load will pull a proxy. What I don't > understand is why the differences in regards to locking, and how > careful/concerned I need to be. > > And given that I'm clearly too undignified for Fabio's valuable time and > attention, if anyone else might correct the mental model I have of how this > works, I'd appreciate it. > > My belief is/was that: (1) an IIS has a thread pool to server requests; (2) > as a result, different requests in an application may be handled by > different threads; (3) since the NHib session isn't thread-safe, you need to > use a session-per-request model for apps - and, in this context, different > sessions could be accessing the same instances - thus my locking test below > that has 2 sessions. > > Remi. > > > -----Original Message----- > From: Oskar Berggren [mailto:[email protected]] > Sent: November 23, 2009 11:28 AM > To: [email protected] > Subject: Re: [nhusers] how should optimistic concurrency using a version > field work? > > It is according to documentation. > > /Oskar > > > 2009/11/23 Rémi Després-Smyth <[email protected]>: >> Thanks Oskar - you're right, it did. Using 'Get' gives me the behavior > I'd >> expect, while using Load does not. I'm not sure what to think about this. >> >> Remi. >> >> >> -----Original Message----- >> From: Oskar Berggren [mailto:[email protected]] >> Sent: November 23, 2009 10:43 AM >> To: [email protected] >> Subject: Re: [nhusers] how should optimistic concurrency using a version >> field work? >> >> Did the changes I suggested make a difference? >> >> /Oskar >> >> >> 2009/11/23 Rémi Després-Smyth <[email protected]>: >>> Clearly I don’t have a correct understanding of how it works then. Can I >>> bother you to clarify where I’m wrong, so I can learn? I’m not looking >> for >>> an answer to a specific problem, I want to understand. >>> >>> >>> >>> Regards, >>> >>> Remi. >>> >>> >>> >>> >>> >>> From: Fabio Maulo [mailto:[email protected]] >>> Sent: November 23, 2009 10:26 AM >>> To: [email protected] >>> Subject: Re: [nhusers] how should optimistic concurrency using a version >>> field work? >>> >>> >>> >>> no. >>> >>> 2009/11/23 Rémi Després-Smyth <[email protected]> >>> >>> Fabio, >>> >>> There wouldn’t be two transactions on the same thread, but I’m working on >> a >>> web app, so different worker threads would be running using different >>> sessions. I did not think setting up a test that uses two different >> threads >>> to be necessary to test the scenario – instead, I just used two different >>> sessions, which is close enough to how it would work in production > anyhow. >>> >>> >>> >>> I don’t think this is an invalid question to be asking. The app’s on a >> web >>> server, and concurrent requests are processed by different worker > threads, >>> aren’t they? Setting up a test that uses two distinct threads would be >>> unnecessary and unreliable, since it would be difficult to ensure correct >>> timing between the two threads for the behaviour I want to see. As a >>> result, I believe the test I setup is actually quite appropriate for what >> I >>> want to check. >>> >>> >>> >>> No? >>> >>> >>> >>> Remi. >>> >>> >>> >>> From: Fabio Maulo [mailto:[email protected]] >>> Sent: November 21, 2009 10:48 AM >>> To: [email protected] >>> Subject: Re: [nhusers] how should optimistic concurrency using a version >>> field work? >>> >>> >>> >>> is that ;) >>> >>> btw what I mean, is that the tests is not well formed in many sense. >>> >>> If our friend Remi want test NH behaviour he should try to recreate a >>> behaviour-test using a more real scenario trying to reproduce how > "things" >>> happens in his application. >>> >>> For example... How Remí can recreate that sequence of actions in a real >> app >>> ? >>> >>> Even if he can, how much is correct to have two opened transactions in > the >>> same thread ? >>> >>> ... and so on... >>> >>> >>> >>> 2009/11/21 Oskar Berggren <[email protected]> >>> >>> Fabio, are you referring to the fact he assigns a string to b, instead >>> of to b.Prop2? I noticed, but ignored that, and it was corrected in >>> another mail. Or is there something else I'm missing? >>> >>> /Oskar >>> >>> >>> 2009/11/21 Fabio Maulo <[email protected]>: >>> >>>> Oskar, that code can't be compiled (try to compile it by eyes). >>>> >>>> 2009/11/20 Oskar Berggren <[email protected]> >>>>> >>>>> This is somewhat of a guess, but I suspect you will see the expected >>>>> behavior if you replace Load with Get. Or don't commit sess1 until >>>>> after you've modified b. >>>>> >>>>> Get fetches the object immediately, while Load returns a proxy, not >>>>> loading the object until you first access one of it's properties. This >>>>> should cause b to actually show the value committed in sess1, the way >>>>> your code looks now. >>>>> >>>>> /Oskar >>>>> >>>>> >>>>> 2009/11/20 Rémi Després-Smyth <[email protected]>: >>>>> > 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 = "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=. >>>>> >>>>> >>>> >>>> >>>> >>>> -- >>>> Fabio Maulo >>>> >>>> -- >>>> >>>> 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=. >>> >>> >>> -- >>> Fabio Maulo >>> >>> -- >>> >>> 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=. >>> >>> >>> -- >>> Fabio Maulo >>> >>> -- >>> >>> 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=. >>> >> >> -- >> >> 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=. >> >> >> > > -- > > 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=. > > > -- 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=.
