概述:使用NHibernate,我正在尝试使用连接的子类进行3层次的层次结构。有一个Category,它继承自AuditableEntity(用于添加PreUpdate和PreInsert审计跟踪),最终从实体继承。
问题:没有任何对AuditableEntity对象的数据更改,这些更改与Ayende的博客文章完全相同,都会持久保存到数据库中。 PreUpdate代码成功更新了AuditableEntity对象属性,但就好像NHibernate没有看到AuditableEntity那样脏,因为没有更新sql语句。
Hbm :
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Learning"
namespace="Learning.entities">
<class name="Entity" >
<id name="Id" type="guid">
<generator class="guid.comb"></generator>
</id>
<version name="Version"/>
<joined-subclass name="AuditableEntity" >
<key column="AuditableEntity_id"></key>
<property name="CreatedOn" ></property>
<property name="CreatedBy" ></property>
<property name="LastModifiedOn" ></property>
<property name="LastModifiedBy" ></property>
<joined-subclass name="Category">
<key column="AuditableEntity_id"></key>
<property name="Name" />
</joined-subclass>
</joined-subclass>
</class>
</hibernate-mapping>
听众的NHibernate配置:
<event type="pre-insert">
<listener class="Learning.eventlisteners.AuditInsertEventListener, Learning" />
</event>
<event type="pre-update">
<listener class="Learning.eventlisteners.AuditUpdateEventListener, Learning" />
</event>
预先更新代码:
namespace Learning.eventlisteners
{
public class AuditInsertEventListener : IPreInsertEventListener
{
public bool OnPreInsert(PreInsertEvent @event)
{
var audit = @event.Entity as IAuditable;
if (audit == null)
return false;
var createdOn = DateTime.Now;
var createdBy = loggedOnProfile;
AuditCommon.Set(@event.Persister, @event.State, "CreatedOn", createdOn);
AuditCommon.Set(@event.Persister, @event.State, "CreatedBy", createdBy);
AuditCommon.Set(@event.Persister, @event.State, "LastModifiedOn", createdOn);
AuditCommon.Set(@event.Persister, @event.State, "LastModifiedBy", createdBy);
audit.CreatedOn = createdOn;
audit.CreatedBy = createdBy;
audit.LastModifiedOn = createdOn;
audit.LastModifiedBy = createdBy;
return false;
}
}
public static class AuditCommon
{
internal static void Set(IEntityPersister persister, IList<object> state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index == -1)
return;
state[index] = value;
}
}
public class AuditUpdateEventListener : IPreUpdateEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
var audit = @event.Entity as IAuditable;
if (audit == null)
return false;
var lastModifiedOn = DateTime.Now.AddSeconds(28);
var lastModifiedBy = loggedOnProfile;
AuditCommon.Set(@event.Persister, @event.State, "LastModifiedOn", lastModifiedOn);
AuditCommon.Set(@event.Persister, @event.State, "LastModifiedBy", lastModifiedBy);
audit.LastModifiedOn = lastModifiedOn;
audit.LastModifiedBy = lastModifiedBy;
return false;
}
}
}
代码:
using (var session = SessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var category = session.Query<Category>().First();
category.Name = "Updated";
session.SaveOrUpdate(category);
transaction.Commit();
}
观察:如果我在调用SaveOrUpdate之前手动更新其中一个AuditableEntity属性,则显然会触发PreUpdate事件并进行适当的数据更改,然后将AuditableEntity数据持久保存到数据库
using (var session = SessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var category = session.Query<Category>().First();
category.Name = "Updated";
category.CreatedOn = DateTime.Now;
session.SaveOrUpdate(category);
transaction.Commit();
}
帮助:我显然不想虚拟编辑AuditableEntity属性,所以我在这里做错了什么想法?
答案 0 :(得分:0)
为了回答这个问题,我撰写了一篇nhibernate.info WIKI文章 - http://nhibernate.info/doc/howto/various/changing-values-in-nhibernate-events
摘要;使用NHibernate事件模型的审计跟踪通常使用OnPreInsert和OnPreUpdate事件侦听器来更改/修改实体的状态。虽然这确实有效并且被广泛记录为解决方案,但应该注意OnPreInsert和OnPreUpdate事件不是用于更改实体的值,而是应该用于检查值,因此它们返回“否决”。
来自Fabio的更新博文 - http://fabiomaulo.blogspot.com/2011/05/nhibernate-bizarre-audit.html