我有一个带有“版本”列的表,用于并发检查,映射如下:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true" auto-import="false" assembly="New1.Backend" namespace="New1.BO">
<class name="VersionedTable" table="`VersionedTables`" schema="`dbo`">
<cache usage="read-write" />
<id name="Id" column="`Id`" type="System.Int32" >
<generator class="NHibernate.Id.Enhanced.TableGenerator">
<param name="increment_size">200</param>
<param name="segment_value">VersionedTables</param>
<param name="optimizer">pooled-lo</param>
</generator>
</id>
<version name="Version" column="`Version`" generated="never" ></version>
<property name="Attribute" column="`Attribute`" type="String" not-null="false" length="100" />
</class>
</hibernate-mapping>
如您所见,我使用名为{strong>版本的列,类型为Integer
。
现在,这是我的问题(我将通过一个演练示例进行解释):
我在两个不同的浏览器页面中打开相同的记录。从SQL事件探查器中,我看到它们的版本为[1]
我在第一页更改了记录。我的SQL事件探查器显示执行的SQL查询为:update VersionedTable set Attribute='A', Version=2 where Id=[id] and Version=1
注意,版本已正确增加到[2]
现在我进入第二个窗口。请记住,我已经加载了以前的记录。它认为版本仍然是[1]。
我更改值,然后按“保存”。 (从Controller动作的数据中,我还看到我得到的版本是“陈旧的”版本:[1])
现在,我的SQL事件探查器向我显示的是:update VersionedTable set Attribute='B', Version=3 where Id=[id] and Version=2
(哎呀!)
请注意,在进行Flushing时,该过程获得了该版本的更新值,而不是使用“陈旧的”版本!我不知道这是如何,何时或为什么发生的。我所知道的是,尽管应该抛出StaleObject异常 ,但两个并发记录都在更新中,两个都优雅地增加了版本!
有人知道为什么会发生这种情况吗?我该如何制止呢? 提前非常感谢!
答案 0 :(得分:0)
这不是陈旧状态的情况。当您在两个浏览器页面中加载同一条记录时,用于加载这些记录的ISession
将关闭。现在,您在页面上查看的是控制器返回的数据,会话已关闭。
如果您要实现“每次请求会话”之类的功能,则会话将随请求本身关闭。您的两个UPDATE动作都会在具有两个新ISession
实例的两个新请求上执行。
即使您使用的会话级别低于“请求”级别,也是如此。
现在,您尚未包含有关如何更新数据的代码。以下是猜测。
从首页保存时,将通过新的ISession
重新读取记录并进行更新。从第二页保存时,您再次重新读取记录并抛出新的ISession
并进行更新。
如您所见,每次都有一个新会话,而不是过时状态。