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

时间:2014-08-18 19:05:59

标签: c# nhibernate has-many

我正在使用一个具有多个域对象的应用程序,这些域对象具有自己的映射到类似的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集合的更改能够级联。但事实并非如此。

调试时我已经验证了集合中存在预期值,但数据库中没有修改任何内容,也没有尝试通过SHOW_SQL日志进行任何操作。如果在此过程中我修改了父项上的非关系属性,则更改确实在父项上保留,但子项保持不变。

是否有正确的方法来配置侦听器以在级联中修改HasMany的子级?

2 个答案:

答案 0 :(得分:0)

我想说,答案可以在这个Q& A:

中找到

事实上,这是在Ayende的文章中:

  

......然而,这是微妙的。我们不能只更新实体状态。原因很简单,实体状态从实体中提取并置于实体状态,我们对实体状态所做的任何更改都不会反映在实体本身中。导致数据库行和实体实例不同步,并导致一大堆非常讨厌的问题,你不知道从哪里开始调试。

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

  

您必须在这两个事件侦听器中更新实体和实体状态(顺便说一下,在其他侦听器中不一定是这种情况)。

一个小代码片段,必须根据上述需要调整(处理集合元素)

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;
}

因此,保持实体实体状态更新,这将是解决方案。

答案 1 :(得分:0)

我希望问题是.Inverse()语句。这基本上告诉NHibernate该位置负责级联而不是父域对象...删除Inverse()会使级联正常工作。