【问题标题】:NHibernate - how to audit all fields of entity?NHibernate - 如何审计实体的所有领域?
【发布时间】:2012-04-28 01:25:54
【问题描述】:

我正在使用 NHibernate 并寻找一种解决方案,可以让我审核对实体中所有字段的更改。我希望能够为每个实体创建一个历史表,即用户 - > UsersHistory,它将具有与用户表相同的结构和其他字段,如操作类型(更新、删除)、进行更改的用户的用户 ID 等。我不'不想为每个实体定义这样的类。我正在寻找类似History<T>(即History<User>)的东西,因为这些条目不属于我的域,只会用于准备对实体所做的更改列表。我还认为在代码中创建对这些表的插入而不是创建 sql 触发器会更好。基本上,我只需要在更新或删除时在历史表中创建一个记录副本,并且我希望插入由 NHibernate 生成。我还需要从历史表中读取记录——正如我所说,这些表将由实体字段和一些常见的历史字段组成。

我找不到有关如何创建此类解决方案的指导。如果我已经在实体上有这样的字段,我能找到的只是添加 UserModified、UpdatedTimestamp 等。但是,我需要实体的完整历史记录,而不仅仅是上次更改条目的信息。

提前感谢您的帮助。

【问题讨论】:

    标签: c# .net hibernate nhibernate


    【解决方案1】:

    NHibernate 有一个很酷的开源审计跟踪,称为 nhibernate.envers https://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

    【讨论】:

    • 这看起来很棒!我目前正在测试它。
    【解决方案2】:

    我认为最好的解决方案是使用事件监听器:

    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 编写处理程序。
    • 集合/关系有一个变通办法,但我找不到博客文章,虽然是 2010 年的,上周正在查看但尚未实施。
    • @Phill 你能给我一个插入/删除听众的链接吗?
    【解决方案3】:

    您正在寻找的是事件监听器(不幸的是,我无法链接到相关文档,因为 nhforge.org wiki 正在经历 NRE...)。

    查看Complex NHibernate Auditing

    【讨论】:

      【解决方案4】:

      下面是一个完整的示例:http://www.shawnduggan.com/?p=89

      这篇文章也有介绍:Audit logging nhibernate

      【讨论】:

        猜你喜欢
        • 2015-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-26
        • 2011-08-01
        相关资源
        最近更新 更多