当时,NHibernate 不会抛出 StaleObjectStateException数据库中使用和更改的数据
我有一个在 NHibernate 中映射的实体,具有乐观并发控制,使用 SQL 时间戳列作为版本号。映射如下:
<class name="Entity" optimistic-lock="version" discriminator-value="0">
<id name="id">
<generator class="native" />
</id>
<version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
...
<subclass name="ChildEntity" discriminator-value="1" />
</class>
我正在测试当数据库中的一行数据在记录的获取和更新之间发生变化时会发生什么。为此,我直接针对表中正在由 NHibernate 更新的记录之一运行更新语句。此直接更新更改表中记录的版本号。
正如预期的那样,NHibernate 托管更新不会发生在特定行上(这很好)。但是,在提交期间不会引发异常。我预计在提交事务时会发生 StaleObjectStateException,以便我可以回滚事务并通知用户。这不是预期的行为吗?我错过了什么吗?
我提交事务的代码如下所示:
_session.BeginTransaction();
...
// load objects in session
IList<ChildEntity> toChange = _session.Find('some condition');
foreach ( var itemToChange in toChange )
{
itemToChange.Status = Status.Updated;
}
...
_session.Transaction.Commit();
这些项目属于同一会话,并且所有工作都在单个事务中完成。 ChildEntity 是 Entity 基类的子类,它的乐观锁设置为版本。
I have an entity mapped in NHibernate with optimistic concurrency control using a SQL timestamp column as the version number. The mapping is like the following:
<class name="Entity" optimistic-lock="version" discriminator-value="0">
<id name="id">
<generator class="native" />
</id>
<version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
...
<subclass name="ChildEntity" discriminator-value="1" />
</class>
I am testing what happens when the data in a row in the database changes between the get and the update of the record. To do so, I am running an update statement directly against one of the records in the table that are in the process of being updated by NHibernate. This direct update changes the version number of the record in the table.
As expected, the NHibernate managed update does not occur on the specific row (this is good). However, no exception is thrown during the commit. I expected a StaleObjectStateException to occur when the transaction was committed so that I could roll back the transaction and inform the user. Isn't this the expected behavior? Am I missing something?
My code to commit the transaction looks something like this:
_session.BeginTransaction();
...
// load objects in session
IList<ChildEntity> toChange = _session.Find('some condition');
foreach ( var itemToChange in toChange )
{
itemToChange.Status = Status.Updated;
}
...
_session.Transaction.Commit();
The items belong to the same session and all work is completed within a single transaction. ChildEntity is a subclass of the Entity base class, which has the optimistic-lock set to version.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你如何修改数据?仅当 NHibernate 尝试更新行且版本号不再相同时,才会引发 StaleObjectException。其他列无关。是否有可能在您的测试中没有更新版本号?
前提是这样的:
A. 用户A& B 从数据库中获取版本 = 1 SQL 的对象
:
SELECT [object] FROM [TABLE] where id = [id] and Version = 1
B. 用户 A 更新对象,将版本更改为 2
SQL:
UPDATE [TABLE] SET [object] (&Set Version = 2) where id = [id] and Version = 1
返回 1 行已更新C. 用户 B 尝试更新对象,但更新时收到 StaleObjectException版本 = 1 的对象(他在步骤 1 中获得的版本)更新数据库中的 0 条记录。
SQL:
UPDATE [TABLE] SET [object] where id = [id] and Version = 1
返回 0 行更新并抛出 StaleObjectException。How are you modifying the data? The StaleObjectException is thrown only when NHibernate attempts to update the row and the version number is no longer the same. The other columns are irrelevant. Is it possible that in your testing you are not updating the version number?
The premise is this:
A. User A & B get object from database with version = 1
SQL:
SELECT [object] FROM [TABLE] where id = [id] and Version = 1
B. User A Updates object which changes the version to 2
SQL:
UPDATE [TABLE] SET [object] (& Set Version = 2) where id = [id] and Version = 1
returns 1 row updatedC. User B attempts to update object but gets StaleObjectException as update object with version = 1 (the version he got it step 1) updates 0 records in the database.
SQL:
UPDATE [TABLE] SET [object] where id = [id] and Version = 1
returns 0 rows updated and StaleObjectException thrown.看来我的测试不准确。在测试中,我在其他事务更新记录后进行获取。此其他更新使该行不符合更新条件,因此未尝试更新。当我更改测试以在 Get 之后进行竞争更新时,会按预期抛出 StaleObjectStateException 。
抱歉造成混乱。
It appears that my testing was inaccurate. In the test, I was doing the get AFTER the other transaction updated the record. This other update made the row ineligible for the update, so no update was attempted. When I changed the test to make the competing update AFTER the Get, then the StaleObjectStateException was thrown as expected.
Sorry for the confusion.