Nhibernate IPreUpdateEventListener和dynamic update=";“真的”;

Nhibernate IPreUpdateEventListener和dynamic update=";“真的”;,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,我一直在尝试下面一个非常简单的审计场景,这似乎是每个人在涉及IPreUpdateEventListener和IPreInsertEventListener时都会引用的资源 然而,无论我怎么努力,我都无法让它发挥作用。事件正确触发,当我通过它时,一切看起来都正常,但没有向数据库发布我的“changedtime”更新 我花了大约一天的时间在谷歌上搜索,终于找到了答案 当您使用dynamic update=“true”映射实体时,它将不起作用。果然,我就是这样。由于我很难找到这段信息,使用dynami

我一直在尝试下面一个非常简单的审计场景,这似乎是每个人在涉及IPreUpdateEventListener和IPreInsertEventListener时都会引用的资源

然而,无论我怎么努力,我都无法让它发挥作用。事件正确触发,当我通过它时,一切看起来都正常,但没有向数据库发布我的“changedtime”更新

我花了大约一天的时间在谷歌上搜索,终于找到了答案

当您使用dynamic update=“true”映射实体时,它将不起作用。果然,我就是这样。由于我很难找到这段信息,使用dynamic update=“true”是否不常见?我们在所有实体上都使用它

由于这对我们来说是一个重大的转折点,我想问一下是否有任何办法可以解决这个问题

我一直在看IInterceptor,但它总是被认为是过时的,那么它的缺点是什么呢?此外,我还没有找到一个关于如何使用IInterceptor(我是NHibernate的新手)归档相同审计(使用插入/更新时间戳)的真正好的教程


任何帮助都将不胜感激

我遇到了这个问题。我就是这样修复的:

public class MyFlushEntityEventListener : DefaultFlushEntityEventListener
{
    protected override void DirtyCheck(FlushEntityEvent e)
    {
        base.DirtyCheck(e);
        if (e.DirtyProperties != null &&
            e.DirtyProperties.Any() &&
            //ITrackUpdate is my inteface for audited entities
            e.Entity is ITrackUpdate)
            e.DirtyProperties = e.DirtyProperties
             .Concat(GetAdditionalDirtyProperties(e)).ToArray();
    }

    static IEnumerable<int> GetAdditionalDirtyProperties(FlushEntityEvent @event)
    {
        yield return Array.IndexOf(@event.EntityEntry.Persister.PropertyNames, 
                                   "UpdateTime");
        yield return Array.IndexOf(@event.EntityEntry.Persister.PropertyNames, 
                                   "UpdateUser");
        //You can add any additional properties here.
        //Some of my entities do not track the user, for example.
    }
}
公共类MyFlushentyEventListener:DefaultFlushentyEventListener
{
受保护覆盖无效目录检查(FlushEntityEvent e)
{
基础。DirtyCheck(e);
如果(如dirtyproperty!=null&&
e、 dirtyProperty.Any()&&
//ITrackUpdate是我的审计实体界面
e、 实体为ITrackUpdate)
e、 dirtyproperty=e.dirtyproperty
.Concat(getAdditionalDirtyproperty(e)).ToArray();
}
静态IEnumerable GetAdditionalDirtyproperty(FlushEntityEvent@event)
{
产生返回数组.IndexOf(@event.EntityEntry.Persister.PropertyNames,
“更新时间”);
产生返回数组.IndexOf(@event.EntityEntry.Persister.PropertyNames,
“更新者”);
//您可以在此处添加任何其他属性。
//例如,我的一些实体不跟踪用户。
}
}
然后,只需替换NH配置文件中的事件侦听器:

<listener type="flush-entity"
          class="MyFlushEntityEventListener, MyAssembly"/>

我也遇到了同样的问题,但是我发现我可以通过使用
OnFlushDirty
来解决这个问题


使用动态更新是不常见的(尽管查找虚拟更新非常有用)。通过动态更新,NHibernate每次都必须生成SQL;如果没有它,它可以重用SQL并替换值。这是我的理解。有趣的是,我不知道。这里的普遍理解是,它必须更加优化,只发送更改的内容,而不是所有内容。@JamieIde:我不同意。我默认使用动态更新,因为它创建了更干净的SQL。我认为性能影响不值得不使用它,但我还没有测量它。很好。与Ayende建议的IPreUpdateListener实现相比,您对它的性能有何看法?@JamieIde:实际上,除了IPreUpdate/InsertEventListener(关注点分离:这只是为了修复动态更新)之外,我还使用了它。没有明显的影响。我开始得到NHibernate.HibernateeException“发现对集合的共享引用:”异常。根本原因是调用AppendListeners而不是SetListeners,因此没有替换默认的flush实体侦听器。希望这能帮上忙,我再也回不到最后一个小时了。