NHibernate在脚下射击:协会所有权和版本控制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NHibernate在脚下射击:协会所有权和版本控制相关的知识,希望对你有一定的参考价值。
情况
假设:
- NHibernate 4
- 父/子关系(一对多),从父到子的单向映射
Inverse(false)
,即父母负责协会Cascade.All
从父母到孩子- 父级和子级都启用了版本控制(在更新记录时自动递增数据库的数据库列)(乐观锁定)
观察到的行为:
- 打开会话和交易。
- 通过一些查询将一些父对象与其子集合一起加载。
- 将新创建的子项添加到子集合中。
- 父母是
SaveOrUpdate
。 - NHibernate首先将子项添加到数据库中,为其提供一个版本。
- 然后它处理父母的关联(因为它负责它)并更新孩子的外键(感谢上帝它可以为空......),增加孩子的版本。但是,它不会更新会话中的子项。
- 最后它应用了级联,并且还在孩子身上调用了
AddOrUpdate
。唯一的问题:它在会话中有一个过时的版本,导致ConcurrencyException
被抛出。 NHibernate正在脚下射击。
题
为什么NHibernate在应用逻辑更新关联时不会更新会话中的子对象?它背后的理由是什么?在我看来,使用版本控制模拟父/子的唯一合理方法是使用Inverse(true)
。
澄清:我对任何变通方法和/或更合适的配置不感兴趣。我知道那些。我只对NHibernate在所述场景中的行为背后的推理感兴趣。
编辑:主要问题似乎是(imo)NHibernate本身并不能完全控制版本控制。相反,它让数据库处理它(至少在我的配置中)。不幸的是,这并不能很好地结合在一起,因为NHibernate在更新与它的关联时不会预期客户端的版本更改,因为从更高级别的视图来看,该关联属于父级,因此子级中没有任何更改。预期。这至少是它背后可能的理由。
NHibernate正在脚下射击。
这不太可能。您的用例非常典型,NH是一个成熟的框架。您可能已经发现了一个错误,但是当NH试图保留它时,更可能是映射或对象图的状态存在问题。
为什么NHibernate在应用逻辑更新关联时不会更新会话中的子对象?
我认为这是因为对协会的更改只会影响父母。如果没有互惠的参考,从实体的角度来看,儿童的任何事情都没有改变。
但是,它不会更新会话中的子项。
你期待什么变化?现在,孩子已与父母联系,但此链接被建模为父母职责的一部分。我想如果孩子持有对其父母的引用可能会有不同的看法,但你还没有说过你的问题是否属于这种情况。
#6粗体部分可能是一个错误,如果你的意思是没有检索到儿童版本并在其上设置它们。检查https://nhibernate.jira.com,如果没有,最终报告完整的测试用例。至少像MCVE。我不是要重现你的情况,因为你的问题让编码工作过多,以至于谁想要检查你的场景发生了什么。我甚至不知道你使用哪种版本控制机制:它们很多,行为不同。 (在你的编辑之后,似乎是一些反击处理的数据库方面。但如果你希望有人研究你的情况发生了什么,以及是否有一个很好的理性背后,或你身边或NHibernate方面的错误,或者只是一个不幸的不支持的功能组合与实际使用的技术,MCVE仍然是必须的:类定义,映射,使用的数据库,使用的软件版本,测试代码与实际再现您的关注。)
现在你可以做些事情:为什么让父母对孩子“负责”呢?这与级联无关,你可能实际上只需要级联。如果您的关系是双向的,让子项映射回其父级,则可能就是这种情况。更多details here。
否则,如果您的关系是单向的,并且如果不需要支持已分离的子级,则应将该键设置为不可为空,并且不要求父级更新。更多details here。这将使用set
完成工作,但会产生list
的问题,例如列表中没有索引更新和漏洞。
以上是关于NHibernate在脚下射击:协会所有权和版本控制的主要内容,如果未能解决你的问题,请参考以下文章
Swift:删除嵌入在导航控制器中的表格视图控制器页脚下方的空间
如何绕过 NHibernate 版本控制更新 SQL 中的记录