使用事件在NHibernate中进行数据审计

时间:2009-03-09 16:13:23

标签: c# .net nhibernate reflection

我正在重新审视并重新实现导致我在NHibernate中询问this question数据审核的代码。但是这一次,我想要使用Sean Carpentersuggestion并实现ISaveOrUpdateEventListener(NHibernate 2.x中的新增功能)

我想在数据库中为每个属性添加一行,使用旧值和新值,以便稍后在UI中我可以说像这样的东西用户Bob将Wibble的属性从A更改为B 2009年3月9日21:04“

比较对象状态以确定哪个对象的属性已更改的最佳方法是什么?

您可以通过以下方式获取对象的加载状态:

    public void OnSaveOrUpdate(SaveOrUpdateEvent saveOrUpdateEvent)
    {
       object[] foo = saveOrUpdateEvent.Entry.LoadedState;
    }

我想我可以使用反射来确定哪些属性已经改变,但我一直在挖掘,似乎没有一组匹配的匹配属性。我原以为会有一个GetChangedProperties()方法。

我可以随时从数据库中获取旧对象并进行比较,但这又是另一个数据库命中,在这种情况下看起来很重要。

最好的方向是什么?

P.S。如果它有任何区别,这是一个ASP.NET-MVC / S#arp架构项目。

3 个答案:

答案 0 :(得分:11)

您还可以使用Persister上的FindDirty方法让NHibernate为您进行比较:

var dirtyFieldIndexes = @event.Persister.FindDirty(@event.State, @event.OldState, @event.Entity, @event.Session);

foreach (var dirtyFieldIndex in dirtyFieldIndexes)
{
    var oldValue = @event.OldState[dirtyFieldIndex];
    var newValue = @event.State[dirtyFieldIndex];

    // Log values to new "AuditLog" object and save appropriately.
}

答案 1 :(得分:6)

我不知道如何使用ISaveOrUpdateListener接口实现您想要的功能 - 但您可以利用IPreUpdateEventListenerIPreInsertEventListener接口都提供您所需的功能。例如做这样的事情:

public bool OnPreUpdate(PreUpdateEvent evt)
{
    string[] names = evt.Persister.PropertyNames;
    for(int index = 0; index < names.Length; index++)
    {
        // compare evt.State[index] to evt.OldState[index] and get
        // the name of the changed property from 'names'
        // (...)
    }
}

并为预插入做同样的事情。

答案 2 :(得分:0)

您可以通过 ILoadEventListener 实现Memento模式以从初始Load序列化状态。显然,您不希望存储集合/关系,或者您要复制整个对象图。然后,您可以将其拉出来并在 ISaveOrUpdateEventListener 中进行比较。