NHibernate - 如何审计实体的所有字段?

10
我正在使用NHibernate,并寻找一种解决方案,以允许我审核实体中所有字段的更改。我想为每个实体创建一个历史表,例如Users -> UsersHistory,该表将具有与Users表相同的结构和附加字段,例如操作类型(更新、删除),执行更改的用户的userid等。 我不想为每个实体定义这样的类。我正在寻找像History<T>这样的东西(例如History<User>),因为这些条目并不属于我的领域,只会用于准备所做的更改列表。我认为最好在代码中创建这些表的插入,而不是创建SQL触发器。基本上,我只需要在更新或删除时创建记录的副本,并且我希望NHibernate生成插入。我还需要从历史表中读取记录 - 正如我所说,这些表将由实体字段和一些常见的历史字段组成。
我找不到如何创建这样的解决方案的指导。我只能找到如果我已经在实体上有这样的字段,则添加UserModified,UpdatedTimestamp等内容。但是,我需要完整的实体历史,而不仅仅是最后更改条目的信息。
谢谢提前帮助。
4个回答

16

有一个很酷的、开源的NHibernate审计跟踪工具,叫做nhibernate.envershttps://bitbucket.org/RogerKratz/nhibernate.envers,因此您不必重新发明轮子。

它可以透明地集成到NHibernate中,无需更改您的领域模型或映射。

添加引用并调用:

var enversConf = new FluentConfiguration(); 
enversConf.Audit<User>();
nhConf.IntegrateWithEnvers(enversConf);

nhConf是你的NHibernate配置对象。

对于你的对象上的每个更改,都会创建一个新的版本。你可以调用Envers来检索一个修订版本:

var reader = AuditReaderFactory.Get(session);
var userInRevOne = reader.Find<User>(user.Id, 1);
或者列出所有的修订版本等等。修订数据本身可以附加用户名、用户ID、时间戳等(任何你能想到的)。
编辑: 它可以在NuGet上获得:http://nuget.org/packages/NHibernate.Envers

这看起来很不错!我正在进行测试。 - empi

5
我认为最好的解决方案是使用事件监听器: http://darrell.mozingo.net/2009/08/31/auditing-with-nhibernate-listeners/ 我写了类似上述链接中的代码(在找到该博客后进行了修改),但我将结果存储在XML中。
例如:
public void OnPostUpdate(PostUpdateEvent updateEvent)
{
    if (updateEvent.Entity is AuditItem)
        return;

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

    var data = new XElement("AuditedData");

    foreach (var dirtyFieldIndex in dirtyFieldIndexes)
    {
        var oldValue = GetStringValueFromStateArray(updateEvent.OldState, dirtyFieldIndex);
        var newValue = GetStringValueFromStateArray(updateEvent.State, dirtyFieldIndex);

        if (oldValue == newValue)
        {
            continue;
        }

        data.Add(new XElement("Item",
                              new XAttribute("Property", updateEvent.Persister.PropertyNames[dirtyFieldIndex]),
                              new XElement("OldValue", oldValue),
                              new XElement("NewValue", newValue)
                             ));
    }

    AuditService.Record(data, updateEvent.Entity, AuditType.Update);
}

审核服务只是添加一些额外的数据,比如IP地址、用户(如果有的话)、它是通过网站或用户操作进行的系统/服务更新等等。然后在我的数据库中,我将XML存储如下:
<AuditedData>
  <Item Property="Awesomeness">
    <OldValue>above average</OldValue>
    <NewValue>godly</NewValue>
  </Item>
  <Item Property="Name">
    <OldValue>Phill</OldValue>
    <NewValue>Phillip</NewValue>
  </Item>
</AuditedData>

我还有插入/删除监听器。

我写了类似的东西,但在测试时发现该解决方案不适用于集合、组件等,因此您最终需要编写 OnPostInsertOnPostUpdateOnPostDeleteOnPreUpdateCollectionOnPreRemoveCollectionOnPostRecreateCollection 的处理程序。 - Andreas
对于集合/关系,有一个解决方法,但我找不到那篇博客文章了。它是在2010年的,上周看过,但尚未实施。 - Phill
@Phill,你能否给我提供插入/删除监听器的链接? - Haidar

0
你要找的是事件监听器(不幸的是,我无法链接到相关文档,因为 nhforge.org 维基正在经历 NRE...)。
请查阅 NHibernate 复杂审计

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接