我正在使用一个具有多个域对象的应用程序,这些域对象具有自己的映射到类似的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
的子级?
答案 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()会使级联正常工作。