NHibernate IPreUpdateEventListener,IPreInsertEventListener没有保存到DB

时间:2014-07-23 10:46:24

标签: c# mysql nhibernate orm

我试图对我的实体实施简单的审核。可审计实体实施ITimestampable接口,该接口定义DateAddedDateModified属性。

我创建并注册了一个事件监听器来填充这些值。这是完整的代码。

internal class TimeStampEventListener : IPreUpdateEventListener, IPreInsertEventListener
    {
        public bool OnPreUpdate(PreUpdateEvent e)
        {
            if (e.Entity is ITimestampable)
            {
                (e.Entity as ITimestampable).DateModified = DateTime.Now;
            }

            return false;
        }

        public bool OnPreInsert(PreInsertEvent e)
        {
            if (e.Entity is ITimestampable)
            {
                (e.Entity as ITimestampable).DateAdded = DateTime.Now;
            }

            return false;
        }

        public void Register(Configuration configuration)
        {
            configuration.SetListener(ListenerType.PreInsert, this);
            configuration.SetListener(ListenerType.PreUpdate, this);
        }
    }

现在,当我进行会话刷新时,会调用侦听器,正确设置审计属性,但大多数时候它们不会保存到数据库中。大多数时候"我的意思是很少值实际上持久存在。我不确定,但看起来应用程序启动后第一次插入/更新,这更奇怪。

当然,首先我对实体进行更改,更改会保留,但审计属性不会。

当我在分析器中查看生成的SQL时,我发现在查询中发送的是NULL而不是当前时间,因此我猜测它不是数据库问题。顺便说一句。我使用的是MySQL,DateAddedDateModified列是DATE类型。

在NHibernate站点上,这些属性仅映射为<property>。也许我错过了一些&#34;特别的&#34;这些案例的映射......?

我完全坚持这一点。任何形式的帮助表示赞赏。

1 个答案:

答案 0 :(得分:3)

答案将在Ayende的文章中隐藏/揭示

  

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

     

您必须在这两个事件侦听器中同时更新实体和实体状态(顺便说一下,在其他侦听器中不一定如此)。以下是使用这些事件侦听器的简单示例:

这是代码,显示如何,来自同一篇文章:

public class AuditEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
    public bool OnPreUpdate(PreUpdateEvent @event)
    {
        var audit = @event.Entity as IHaveAuditInformation;
        if (audit == null)
            return false;

        var time = DateTime.Now;
        var name = WindowsIdentity.GetCurrent().Name;

        Set(@event.Persister, @event.State, "UpdatedAt", time);
        Set(@event.Persister, @event.State, "UpdatedBy", name);

        audit.UpdatedAt = time;
        audit.UpdatedBy = name;

        return false;
    }

    public bool OnPreInsert(PreInsertEvent @event)
    {
        var audit = @event.Entity as IHaveAuditInformation;
        if (audit == null)
            return false;


        var time = DateTime.Now;
        var name = WindowsIdentity.GetCurrent().Name;

        Set(@event.Persister, @event.State, "CreatedAt", time);
        Set(@event.Persister, @event.State, "UpdatedAt", time);
        Set(@event.Persister, @event.State, "CreatedBy", name);
        Set(@event.Persister, @event.State, "UpdatedBy", name);

        audit.CreatedAt = time;
        audit.CreatedBy = name;
        audit.UpdatedAt = time;
        audit.UpdatedBy = name;

        return false;
    }

这是神奇的Set()

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