我正在构建一些简单的审计日志记录功能。我有一个中等规模的实体模型(大约50个实体),我想在大约5或6上实现审计日志记录。最后我想让这个工作在Inserts&删除也是如此,但现在我只关注更新。
问题是,当我从EventListener中将session.Save(或SaveOrUpdate)传递给我的auditLog表时,原始对象会被正确保留(更新),但我的AuditLog对象永远不会被插入。
我认为Pre
和Post
事件监听器在NHibernate保存生命周期中被调用到会话仍然是一个问题。
//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&amp; amp;这个方法中的事务,但这不是很理想,因为代码从监听器方法返回,在我的主应用程序中命中session.Transaction.Commit(),如果该事务失败,那么我有一个我的审计表中的孤立日志消息,表示从未发生过某种情况。
我可能出错的任何指示?
修改
我还尝试使用基于此线程中的一些注释的事件中的子会话来SaveOrUpdate 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);
我的数据库中的日志表中仍然没有显示任何内容。没有错误或例外。
答案 0 :(得分:3)
您需要在OnPreUpdate方法中创建子会话currentSession.GetSession(EntityMode.Poco),并在日志方法中使用它。根据您的flushmode设置,您可能还需要刷新子会话。
此外,您想推出自己的解决方案有什么特别的原因吗?仅供参考,NHibernate Envers现在是一个非常成熟的图书馆。