0

我正在制作一些简单的审计日志功能的原型。我有一个中型实体模型(约 50 个实体),我想在大约 5 或 6 个上实施审计日志记录。最终我也想让它在插入和删除上工作,但现在我只是专注于更新。

问题是,当我从 EventListener 中对我的 auditLog 表执行 session.Save(或 SaveOrUpdate)时,原始对象被正确保存(更新),但我的 AuditLog 对象永远不会被插入。

我认为在 NHibernate 保存生命周期的后期调用事件侦听器Pre和事件侦听器是一个问题,以便会话仍然可以使用。Post

//in my ISessionFactory Build method

nHibernateConfiguration.EventListeners.PreUpdateEventListeners = 
    new IPreUpdateEventListener[]{new AuditLogListener()};


//in my AuditLogListener
public class AuditLogListener : IPreUpdateEventListener
{
    public bool OnPreUpdate(PreUpdateEvent @event)
    {
        string message = //code to look at @event.Entity & build message - this works            
        if (!string.IsNullOrEmpty(message))
            AuditLogHelper.Log(message, @event.Session); //Session is an IEventSource

        return false; //Don't veto the change
    }
}

//In my helper
public static void Log(string message, IEventSource session)
{
    var user = session.QueryOver<User>()
                      .Where(x => x.Name == "John")
                      .SingleOrDefault();
    //have confirmed a valid user is found

    var logItem = new AdministrationAuditLog
                  {
                     LogDate = DateTime.Now,
                     Message = message,
                     User = user
                  };

    (session as ISession).SaveOrUpdate(logItem);
}

当它在最后一个方法中到达 session.SaveOrUpdate() 时,不会发生错误。不抛出异常。它似乎成功并继续前进。但什么也没有发生。审计日志条目永远不会出现在数据库中。

我能够让它工作的唯一方法是在此方法中创建一个全新的 Session & Transaction ,但这并不理想,因为代码从侦听器方法返回,命中 session.Transaction .Commit() 在我的主应用程序中,如果该事务失败,那么我的审计表中会出现一条孤立的日志消息,说明从未发生过的事情。

我可能会出错的任何指示?

编辑

我还尝试使用基于此线程中的一些评论的事件中的子会话来保存或更新 LogItem。http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener

var childSession = session.GetSession(EntityMode.Poco);
var logItem = new AdministrationAuditLog
                {
                    LogDate = DateTime.Now,
                    Message = message,
                    User = databaseLogin.User
                };

childSession.SaveOrUpdate(logItem);

我的数据库中的日志表中仍然没有出现任何内容。没有错误或异常。

4

1 回答 1

3

您需要在 OnPreUpdate 方法中创建一个子会话 currentSession.GetSession(EntityMode.Poco) 并在您的日志方法中使用它。根据您的刷新模式设置,您可能还需要刷新子会话。

此外,您想推出自己的解决方案有什么特别的原因吗?仅供参考,NHibernate Envers 现在是一个非常成熟的库。

于 2014-01-10T09:26:07.343 回答