NHibernate版本没有抛出StaleObjectException,尽管它应该

时间:2019-06-10 13:12:23

标签: nhibernate concurrency versioning nhibernate-mapping

我有一个带有“版本”列的表,用于并发检查,映射如下:

<?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异常 ,但两个并发记录都在更新中,两个都优雅地增加了版本!

有人知道为什么会发生这种情况吗?我该如何制止呢? 提前非常感谢!

1 个答案:

答案 0 :(得分:0)

这不是陈旧状态的情况。当您在两个浏览器页面中加载同一条记录时,用于加载这些记录的ISession将关闭。现在,您在页面上查看的是控制器返回的数据,会话已关闭。

如果您要实现“每次请求会话”之类的功能,则会话将随请求本身关闭。您的两个UPDATE动作都会在具有两个新ISession实例的两个新请求上执行。

即使您使用的会话级别低于“请求”级别,也是如此。

现在,您尚未包含有关如何更新数据的代码。以下是猜测。

从首页保存时,将通过新的ISession重新读取记录并进行更新。从第二页保存时,您再次重新读取记录并抛出新的ISession并进行更新。

如您所见,每次都有一个新会话,而不是过时状态。