Nhibernate 在预插入/预删除事件侦听器中保存新实体不会';不能持久化到数据库
我在NHibernate2.1中配置了预插入和预删除事件侦听器。对于特定表上的插入和删除,我希望将审核事件写入单独的审核表Nhibernate 在预插入/预删除事件侦听器中保存新实体不会';不能持久化到数据库,nhibernate,event-listener,Nhibernate,Event Listener,我在NHibernate2.1中配置了预插入和预删除事件侦听器。对于特定表上的插入和删除,我希望将审核事件写入单独的审核表 public class AuditEventListener : IPreInsertEventListener, IPreDeleteEventListener { private static readonly ILog Log = LogManager.GetLogger(typeof(AuditEventListener)); public b
public class AuditEventListener : IPreInsertEventListener, IPreDeleteEventListener
{
private static readonly ILog Log = LogManager.GetLogger(typeof(AuditEventListener));
public bool OnPreInsert(PreInsertEvent @event)
{
if (!(@event.Entity is IAuditable))
return false;
return AuditEvent(@event.Session.GetSession(EntityMode.Poco),
true, (@event.Entity as IAuditable));
}
public bool OnPreDelete(PreDeleteEvent @event)
{
if (!(@event.Entity is IAuditable))
return false;
return AuditEvent(@event.Session.GetSession(EntityMode.Poco),
false, (@event.Entity as IAuditable));
}
private bool AuditEvent(ISession session, bool isInsert, IAuditable entity)
{
if (entity is ArticleBinding)
{
if (Log.IsDebugEnabled)
Log.DebugFormat(" audit event ({0}), entity is ArticleBinding", ((isInsert) ? "Insert" : "Delete"));
AddArticleBindingAuditEvent(session, isInsert,
(entity as ArticleTagBinding));
}
return false;
}
private void AddArticleBindingAuditEvent(ISession session,
bool isInsert, ArticleBinding binding)
{
var auditRecord = new AuditArticleBinding()
{
ArticleId = binding.ArticleId,
Action = (isInsert) ? "Add" : "Delete",
LoggedBy = string.IsNullOrEmpty(Thread.CurrentPrincipal.Identity.Name)
? "Unknown"
: Thread.CurrentPrincipal.Identity.Name
};
session.Save(auditRecord);
}
}
我解决了使用同一个会话的问题,这导致了一个异常。现在,所有代码都可以正常运行,我的日志语句被命中,但审计记录从未被插入。使用NHProf,我可以看到INSERT调用从未发生过
为什么上面的代码不会导致插入?我目前正在做同样的事情,遇到了同样的问题。尝试保存新实体时,
INSERT
语句甚至没有执行。我发现了一篇文章,其中一条评论询问插入一个新实体,作者回答说需要一个子会话
private void AddArticleBindingAuditEvent(ISession session,
bool isInsert, ArticleBinding binding)
{
var childSession = e.Session.GetSession(EntityMode.Poco);
var auditRecord = new AuditArticleBinding()
{
ArticleId = binding.ArticleId,
Action = (isInsert) ? "Add" : "Delete",
LoggedBy = string.IsNullOrEmpty(Thread.CurrentPrincipal.Identity.Name)
? "Unknown"
: Thread.CurrentPrincipal.Identity.Name
};
childSession.Save(auditRecord);
childSession.Flush();
}
你的另一个参考资料(我今天找到的)是。它给出了一个插入新审核日志的完整示例,但使用了Post侦听器,并且是非实体特定的(与我使用persister查找更改的值的操作几乎相同)。我不确定这比使用前置侦听器有什么好处
作为“以防万一”,您需要确保将事件侦听器连接到您的配置:
var eventListener = new AuditEventListener();
config.SetListener(ListenerType.PreInsert, eventListener);
config.SetListener(ListenerType.PreDelete, eventListener);
全面披露:我是NHibernate的新手,所以如果我错过了什么或者可以做得更好,请告诉我。上述方法适用于我,因为我的记录已成功插入数据库,但在某些情况下确实失败。虽然我几乎可以肯定这是我的应用程序特有的(我对代码库还不熟悉,所以仍在努力解决问题)在花了一整天的时间试图找出问题的根本原因但没有成功后,我希望能找到这一点来解释: 查看Hibernate代码,看起来插入的是 仅使用PreInsertEvent的“state”属性。所以即使 更新event.getEntity(),我认为它不会 在插入阶段插入 解决方案包括1)更新实体以通过验证(如@NotNull)和2)更新状态以在数据库中保留新值 在我的应用程序中,这会生成一个丑陋的代码,如:
@Override
public boolean onPreInsert(PreInsertEvent event) {
Object entity = event.getEntity();
// Assumption: entity cannot be null
if (entity instanceof AbstractBase) {
String[] names = event.getPersister().getPropertyNames();
for (int i = 0; i < names.length; ++i) {
if ("insertWhen".equals(names[i])) {
((AbstractBase<?>) entity).setInsertWhen(new Date());
event.getState()[i] = ((AbstractBase<?>) entity).getInsertWhen();
}
else if (...) {
...
}
}
}
@覆盖
公共布尔值onPreInsert(PreInsertEvent事件){
对象实体=event.getEntity();
//假设:实体不能为空
if(AbstractBase的实体实例){
String[]name=event.getPersister().getPropertyNames();
对于(int i=0;i
我非常惊讶地看到,6年前记录的这个问题对我们许多人来说仍然是个问题
我希望这会有所帮助。更新:通过跟踪,我能够在执行事件侦听器代码之前确定正在提交会话事务。我尝试了后插入/后删除,而不是前插入/前删除,但没有任何区别。为什么在提交事务之前不调用事件侦听器?那就是nds真的违反直觉。你在这方面有什么进展吗?致盲的乔恩,谢谢。有点不同,但这是孩子会议救了我,双关语的意思