NHibernate在脚下射击:协会所有权和版本控制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NHibernate在脚下射击:协会所有权和版本控制相关的知识,希望对你有一定的参考价值。

情况

假设:

  • NHibernate 4
  • 父/子关系(一对多),从父到子的单向映射
  • Inverse(false),即父母负责协会
  • Cascade.All从父母到孩子
  • 父级和子级都启用了版本控制(在更新记录时自动递增数据库的数据库列)(乐观锁定)

观察到的行为:

  1. 打开会话和交易。
  2. 通过一些查询将一些父对象与其子集合一起加载。
  3. 将新创建的子项添加到子集合中。
  4. 父母是SaveOrUpdate
  5. NHibernate首先将子项添加到数据库中,为其提供一个版本。
  6. 然后它处理父母的关联(因为它负责它)并更新孩子的外键(感谢上帝它可以为空......),增加孩子的版本。但是,它不会更新会话中的子项。
  7. 最后它应用了级联,并且还在孩子身上调用了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 的生产版本

SVN版控系统的安装和使用

如何绕过 NHibernate 版本控制更新 SQL 中的记录

NHibernate LINQ 是不是稳定并且项目上的所有 NHibernate 螺栓都允许它

更改 NHibernate 中的初始 LazyLoad 行为