我试图对我的实体实施简单的审核。可审计实体实施ITimestampable
接口,该接口定义DateAdded
和DateModified
属性。
我创建并注册了一个事件监听器来填充这些值。这是完整的代码。
internal class TimeStampEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
public bool OnPreUpdate(PreUpdateEvent e)
{
if (e.Entity is ITimestampable)
{
(e.Entity as ITimestampable).DateModified = DateTime.Now;
}
return false;
}
public bool OnPreInsert(PreInsertEvent e)
{
if (e.Entity is ITimestampable)
{
(e.Entity as ITimestampable).DateAdded = DateTime.Now;
}
return false;
}
public void Register(Configuration configuration)
{
configuration.SetListener(ListenerType.PreInsert, this);
configuration.SetListener(ListenerType.PreUpdate, this);
}
}
现在,当我进行会话刷新时,会调用侦听器,正确设置审计属性,但大多数时候它们不会保存到数据库中。大多数时候"我的意思是很少值实际上持久存在。我不确定,但看起来应用程序启动后第一次插入/更新,这更奇怪。
当然,首先我对实体进行更改,更改会保留,但审计属性不会。
当我在分析器中查看生成的SQL时,我发现在查询中发送的是NULL而不是当前时间,因此我猜测它不是数据库问题。顺便说一句。我使用的是MySQL,DateAdded
和DateModified
列是DATE
类型。
在NHibernate站点上,这些属性仅映射为<property>
。也许我错过了一些&#34;特别的&#34;这些案例的映射......?
我完全坚持这一点。任何形式的帮助表示赞赏。
答案 0 :(得分:3)
答案将在Ayende的文章中隐藏/揭示
......然而,这是微妙的。我们不能只更新实体状态。原因很简单,实体状态是从实体中提取出来并放置在实体状态中,我们对实体状态所做的任何更改都不会反映在实体本身中。这可能是导致数据库行和实体实例不同步,并导致一大堆非常讨厌的问题,你不知道从哪里开始调试。
您必须在这两个事件侦听器中同时更新实体和实体状态(顺便说一下,在其他侦听器中不一定如此)。以下是使用这些事件侦听器的简单示例:
这是代码,显示如何,来自同一篇文章:
public class AuditEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
var audit = @event.Entity as IHaveAuditInformation;
if (audit == null)
return false;
var time = DateTime.Now;
var name = WindowsIdentity.GetCurrent().Name;
Set(@event.Persister, @event.State, "UpdatedAt", time);
Set(@event.Persister, @event.State, "UpdatedBy", name);
audit.UpdatedAt = time;
audit.UpdatedBy = name;
return false;
}
public bool OnPreInsert(PreInsertEvent @event)
{
var audit = @event.Entity as IHaveAuditInformation;
if (audit == null)
return false;
var time = DateTime.Now;
var name = WindowsIdentity.GetCurrent().Name;
Set(@event.Persister, @event.State, "CreatedAt", time);
Set(@event.Persister, @event.State, "UpdatedAt", time);
Set(@event.Persister, @event.State, "CreatedBy", name);
Set(@event.Persister, @event.State, "UpdatedBy", name);
audit.CreatedAt = time;
audit.CreatedBy = name;
audit.UpdatedAt = time;
audit.UpdatedBy = name;
return false;
}
这是神奇的Set()
private void Set(IEntityPersister persister, object[] state
, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index == -1)
return;
state[index] = value;
}