【问题标题】:NHibernate Event Listeners Persistence - how does it work?NHibernate 事件侦听器持久性 - 它是如何工作的?
【发布时间】:2010-11-19 08:19:30
【问题描述】:

我决定在最新版本的 NHibernate 中实现事件侦听器,以跟踪谁在进行编辑以及这些编辑是什么。我的问题是这个 - 下面确实有效,我可以逐步完成,但我不确定这些更改是如何保存的......我是否需要构建一个审计表并为其编写一个映射来调用保存或什么方法最好是通过“更新者”和“更新日期”信息来获取对象的状态,以便我可以在以后为某人提供此信息。

我认为基类提供了这个(或这个功能的一个子集),但我似乎找不到关于我在这里缺少的东西的好的博客文章。任何帮助将不胜感激!

Imports NHibernate.Event
Imports NHibernate.Event.Default

Public Class CustomSaveEventListener
    Inherits DefaultSaveEventListener

    Protected Overloads Overrides Function PerformSaveOrUpdate(ByVal evt As SaveOrUpdateEvent) As Object
        Dim entity As IEntity = TryCast(evt.Entity, IEntity)
        If entity IsNot Nothing Then
            ProcessEntityBeforeInsert(entity)
        End If

        Return MyBase.PerformSaveOrUpdate(evt)
    End Function

    Friend Overridable Sub ProcessEntityBeforeInsert(ByVal entity As IEntity)
        Dim user As User = DirectCast(Thread.CurrentPrincipal, User)
        entity.ModifiedBy = user.UserName
        entity.ModifiedDate = DateTime.Now
    End Sub
End Class

当我打开 Reflector 时,我看到了这个基类方法的以下内容 - 但它到底在做什么?

protected override object PerformSaveOrUpdate(SaveOrUpdateEvent @event)
{
    EntityEntry entry = @event.Session.PersistenceContext.GetEntry(@event.Entity);
    if ((entry != null) && (entry.Status != Status.Deleted))
    {
        return this.EntityIsPersistent(@event);
    }
    return this.EntityIsTransient(@event);
}

【问题讨论】:

    标签: nhibernate persistence event-listener


    【解决方案1】:

    当一个实体被持久化(保存或加载)时,NH 将它添加到一个内部字典(在 session.PersistenceContext 中)。这个字典的键是一个EntityEntry,它包含一些关于实体状态的信息(我猜还有一些其他的东西)。如果实体未保存(瞬态),它将不会在内部字典中找到 EntityKey。

    通过阅读,看起来这个函数看起来实体是否是瞬态的,并调用了好函数(我猜 EntityIsTransient 触发保存行为,EntityIsPersitent 触发更新行为)。

     EntityEntry entry = @event.Session.PersistenceContext.GetEntry(@event.Entity);
        if ((entry != null) && (entry.Status != Status.Deleted))
        {
            return this.EntityIsPersistent(@event);
        }
        return this.EntityIsTransient(@event);
    

    但是关于你的问题,它看起来像一个日志系统。 为什么不直接实现 ISaveOrUpdateEvent 并使用 log4net 来记录编辑?

    【讨论】:

    • 感谢有关 Session.PersistenceContext 的详细信息 - 关于日志记录 我实际上是在尝试保持系统的“历史”行为,而不是使用存储过程来插入历史保存,我希望 NHibernate 为我做这件事。唯一的方法是坚持这样的事情来为 SQL Server 中的历史表创建一个映射文件并在这个类中调用更新? (就在保存或更新事件之后)
    • 不客气。我无法详细回答第二个问题。我不喜欢你的想法。当您拦截保存或更新事件时,NH 已经处于数据库访问和批处理过程中。一旦开始潮红,我尽量不要修改 NH 的行为,因为害怕破坏某些东西。我看到的一个仅限 NH 的解决方案是让您堆叠所有更改,并且在刷新会话后,重做日志类的保存,或者在程序执行结束时。
    • 如果您在 nh 会话中遇到异常(例如连接丢失),这会使事情变得更加复杂。这就是我谈到 log4net (logging.apache.org/log4net/index.html) 的原因。您可以指定您希望它将日志写入数据库或其他东西(查找附加程序)。 log4net 配置一开始有点难以理解,但我敢打赌这是你需要的工具。
    • 我喜欢你用 log4net 暗示的解决方案。关于这种方法的一个问题 - 最好是对对象进行序列化并存储它,还是我应该尝试捕获对象的每个属性并将其与其他详细信息(时间/用户)一起记录?
    • 捕获属性。如果你序列化你的对象,你需要创建一个应用程序来反序列化它。我想如果您想最初使用 NH 将其存储到数据库中,您不想这样做!有关 log4net 的其他问题,您应该重新询问社区或查找文档,我是 log4net 的菜鸟。
    猜你喜欢
    • 1970-01-01
    • 2011-10-14
    • 2014-05-27
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多