NHibernate EventListener是否可以修改HasMany关系的内容?

本文关键字:关系 HasMany 修改 EventListener 是否 NHibernate | 更新日期: 2023-09-27 18:18:38

我正在处理一个应用程序,该应用程序有几个域对象,它们自己映射到类似的HasMany域对象列表。该应用程序运行在棕地数据库之上,因此结构不能轻易更改。每个父级流畅映射看起来类似于:

HasMany(x => x.Locations)   // Location Type applicable to the given parent
    .AsBag()
    .KeyColumn("parent_sk")
    .LazyLoad()
    .Inverse()
    .Cascade.AllDeleteOrphan();

每当父域对象上的位置发生变化时,关联的父对象必须在同一事务中同步其位置属性(添加一些新位置,删除一些位置,保留其他位置)。

我已经创建并注册了一个NHibernate事件监听器,实现了IPreUpdateEventListener, IPreInsertEventListener和IPreDeleteEventListener。当对任何Location域对象进行更改时,此事件侦听器将按预期触发。

一旦被触发,就会找到合适的父类,并操作它们的Location集合,以便添加/删除位置。然后将父类发送到适当的存储库保存方法。我预计地点集合的变化会层叠增加。然而,事实并非如此。

调试时,我已经验证了集合中存在预期的值,但是数据库中没有任何修改,也没有任何尝试,据我所知,通过SHOW_SQL日志。如果在此过程中修改父节点上的非关系属性,则更改确实会在父节点上持久化,但子节点保持不变。

是否有一种正确的方法来配置侦听器来修改级联中HasMany的子节点?

NHibernate EventListener是否可以修改HasMany关系的内容?

我想说,答案可以在这个问题中找到:

  • NHibernate IPreUpdateEventListener, IPreInsertEventListener不保存到DB

实际上是在Ayende的文章中:

  • NHibernate IPreUpdateEventListener;IPreInsertEventListener

…然而,微妙之处就在这里。我们不能仅仅更新实体状态。原因很简单,实体状态是从实体中提取出来并放置在实体状态中,我们对实体状态所做的任何更改都不会反映在实体本身中。这可能会导致数据库行和实体实例不同步,并导致一大堆真正令人讨厌的问题,你不知道从哪里开始调试

以及如何解决这个问题的描述:

你必须在这两个事件监听器中同时更新实体和实体状态(顺便说一下,这在其他监听器中不一定是这样的)…

一个小代码片段,必须根据上面的需求进行调整(处理集合元素)

public bool OnPreUpdate(PreUpdateEvent @event)
{
    ...
    Set(@event.Persister, @event.State, "UpdatedAt", time);
...
// the way how to assure that even the State is updated
private void Set(IEntityPersister persister, object[] state
          , string propertyName, object value)
{
    var index = Array.IndexOf(persister.PropertyNames, propertyName);
    if (index == -1)
        return;
    state[index] = value;
}
因此,保持实体实体状态更新,将是这里的解决方案。

我认为问题出在。inverse()语句上。这基本上告诉NHibernate location负责级联,而不是父域对象…删除逆()将使级联正常工作。