复杂的NHibernate的审计(Complex NHibernate Auditing)

2019-07-30 21:09发布

我使用的是IPostUpdateEventListener接口现在要做的更新审计日志,抓住新旧值,然后储存在“审核”表和所有花言巧语每个更新的领域。 工程膨胀,但有我有一个很难fullfilling最后两个要求:

  1. 显示更新是为哪个员工。
  2. 显示领域最新的“友好”名称。

对于#1,我的第一反应是使用反射和寻找和抓住“雇员”属性对指定的实体找出它是哪个员工,但是当你在图深度是几个对象,迅速分崩离析没有自动的方式要回定Employee对象。

思路来解决第1张,要求所有对象的“父”财产范围,所以我可以遍历使用单独的SQL寻找员工类型(对我来说,会污染我们的领域太多,简单的持久性关注)图作业tranverse的foriegn键和事后填写雇员ID(如寄托都是迄今为止基于代码,我宁愿不维护单独的SQL工作 - 而SQL工作将变得非常讨厌非常快)。

至于第二个要求,我可以得到改变就好了实际属性的名称。 对于一个很好的80% - 我们的田地的90%时,(正确格式化的)属性名称是什么,我们显示,这样我就可以的名称空间基础上,Pascal大小写。 字段的其余部分,但是,不匹配各种原因。 我们正在使用ASP.NET MVC和MvcContrib流利的HTML建设者,但即使我们修改了设置给在视图模型overridess的字段名称应该是什么属性的点(和为此的代码,而不是有它只是视图),还有以匹配视图模型的域对象的属性被保存没有真正的方法。

最后一个务实的解决这两个问题将只是在其他服务中的每个更新操作之后调用审计日志服务,在该领域的名称和员工信息传递的需要,但是,好了,我真的不想去那里明显原因。

对于任何一个问题的想法将不胜感激。 搜索和货架我的大脑几天已经变成了没有用的 - 大多数人似乎停留在简单的旧/新谷记录或只是一个“创建/更新”上记录本身时间戳。

Answer 1:

我有类似你的要求。 就我而言,这是一个健康保障应用和审计日志需要识别到的插入/更新适用病人。

我的解决方案是定义一个接口,它的所有审计类需要实现:

public interface IAuditedRecord
{
    IPatient OwningPatient { get; }

    ...
    // Other audit-related properties (user, timestamp)
}

经审计的类,然后实现这个接口在任何需要的方式。 例如:

public class Medication : IAuditedRecord
{
    // One end of a bidirectional association. Populated by NHibernate.
    private IPatient _patient;

    IPatient OwningPatient { get { return _patient; } }
}

public class MedicationNote : IAuditedRecord
{
    // One end of a bidirectional association. Populated by NHibernate.
    private Medication _medication;

    IPatient OwningPatient { get { return _medication.OwningPatient; } }
}

IPostInsertEventListenerIPostUpdateEventListener然后取OwningPatient以填充审计记录属性。

该解决方案具有保持在事件侦听器的审核逻辑,这是唯一的地方,一个是肯定的插入/更新会发生,以及允许对象及其所属病人之间的间接联系的遍历的优势。

不足之处是经审计类具有一个特定的接口派生。 我认为利大于弊这部小成本。



Answer 2:

这似乎不是一个微不足道的审计线索更复杂的情形,因为这个原因,我会向倾斜的应用服务,以处理这个问题。

  1. 它更多的测试。
  2. 其明确的。
  3. 你不必诉诸反射或共同财产。

我们在应用程序中使用的审计服务,即使我们的情况是比你,因为它是一个域的关注要简单得多。 我们的领域知道的历史与历史的作品,它不只是创造一些报告前端。

正在录制谁(员工)正在更新,或者是员工的某种聚合根的?



Answer 3:

对于#1,我设计了以下内容:在MyCommon组装我声明

public interface IUserSessionStore
{
    UserSession Get();
    void Set(UserSession userSession);
}

它得到每使用Ninject请求而创建。 这个类的实现,只存储在ASPNET MVC届UserSession对象。

有了这个,我可以要求IUserSessionStore贯穿所有层,并得到UserSession此类使用,并在每个对象以将审计信息(以下级将基于myModel项目):

public class AuditUpdater : DefaultSaveOrUpdateEventListener
{
    private IUserSessionStore userSessionStore;
    public AuditUpdater(IUserSessionStore userSessionStore)
    {
        this.userSessionStore = userSessionStore;
    }

    private Guid GetUserId()
    {
        return userSessionStore.Get().UserId;
    }

    private void UpdateAuditCreate(IAuditCreate auditable)
    {
        if (auditable != null)
        {
            auditable.CreationDate = DateTime.UtcNow;
            auditable.CreatedBy = GetUserId();
        }
    }

    .......
}

所以,你可以适应这个以获取你需要你的员工信息。

很高兴我会带更多的建议!



Answer 4:

要创建日志,您可以使用IPostInsertEventListener或IPostUpdateEventListener。 如果你正在使用流利的配置你有配置如示例波纹管。

有一个帖子或更新提交时,事件将被调用。

.ExposeConfiguration(c => c.EventListeners.PostCommitInsertEventListeners = new IPostInsertEventListener[] { new AuditEventPostInsert() })
.ExposeConfiguration(c => c.EventListeners.PostCommitUpdateEventListeners = new IPostUpdateEventListener[] { new AuditEventPostUpdate() });


文章来源: Complex NHibernate Auditing