如何使用NHibernate实现ChangeTime和ChangeUser列?

时间:2009-02-15 22:08:47

标签: nhibernate

我正在尝试将NHibernate与现有数据库一起使用。在数据模型中,每个表中都有列,其中包含对行进行的上次更新的时间和用户名。我如何使用NHibernate做到这一点?

我试图实现一个拦截器,它在使用IInterceptor.OnSave方法保存之前在实体中设置ChangeTime和ChangeUser。这不起作用,因为即使没有修改其他属性,设置这些属性也会触发对行的更新。

如果有任何方法告诉NHibernate排除ChangeTime和ChangeUser属性然后它进行脏检查,它可能有效。但我还没有找到任何办法来实现这一目标。

感谢您的帮助。

4 个答案:

答案 0 :(得分:14)

您应该为预插入和预更新事件注册一个侦听器。您可以通过以下配置完成此操作:

<hibernate-configuration>
    ...
    <event type="pre-update">
        <listener class="MyListener, MyAssembly"/>
    </event>
    <event type="pre-insert">
        <listener class="MyListener, MyAssembly"/>
    </event>
</hibernate-configuration>

然后实现一个监听器 - 这样的东西(可能不完全准确 - 写下我的记忆):

public class MyListener : IPreUpdateEventListener, IPreInsertEventListener
{
    public bool OnPreUpdate(PreUpdateEvent evt)
    {
        if (evt.Entity is IHasLastModified)
            UpdateLastModified(evt.State, evt.Persister.PropertyNames);

        return false;
    }

    public bool OnPreInsert(PreInsertEvent evt)
    {
        if (evt.Entity is IHasLastModified)
            UpdateLastModified(evt.State, evt.Persister.PropertyNames);

        return false;
    }

    void UpdateLastModified(object[] state, string[] names)
    {
        var index = Array.FindIndex(names, n => n == "LastModified");

        state[index] = DateTime.Now;
    }
}

并对预更新事件做同样的事情。

编辑:这个照顾插入和更新,它似乎工作。

答案 1 :(得分:5)

嘿,我只是必须在我正在进行的项目中解决这个问题,这是我的答案

public interface IDateModified
{
    DateTime Created { get; set; }
    DateTime Modified { get; set; }
}

public class CustomDefaultSaveOrUpdateEventListener 
    : DefaultSaveOrUpdateEventListener
{
    protected override object EntityIsPersistent(SaveOrUpdateEvent evt)
    {
        var entity = evt.Entity as IDateModified;
        if (entity != null)
        {
                entity.Modified = DateTime.Now;
        }

        return base.EntityIsPersistent(evt);
    }

    protected override object EntityIsTransient(SaveOrUpdateEvent evt)
    {
        var entity = evt.Entity as IDateModified;
        if (entity != null)
        {
            entity.Created = entity.Modified = DateTime.Now;
        }

        return base.EntityIsTransient(evt);
    }
}

然后在我的配置中(我使用Fluent NHibernate在代码中配置我的单元测试)

configuration.EventListeners.SaveOrUpdateEventListeners 
= new ISaveOrUpdateEventListener[]
{
    new CustomDefaultSaveOrUpdateEventListener() 
};

AWESOMENESSSSSSSS!

答案 2 :(得分:1)

Mookid的回答是正确的虽然我想指出如果使用S#arp架构,NHib配置应该设置如下:

<hibernate-configuration>
    <session-factory>
    ...
        <event type="pre-update">
            <listener class="MyListener, MyAssembly"/>
        </event>
        <event type="pre-insert">
            <listener class="MyListener, MyAssembly"/>
        </event>
    </session-factory>
</hibernate-configuration>

事件元素进入session-factory元素。

答案 3 :(得分:0)

您也可以使用拦截器,而不是使用LIsteners: Audit changes using interceptor