是的。正如大卫所说,EventListener 是你最好的选择。下面是我用审计字段值标记所有实体的示例。
namespace NHibernate.Extensions.EventListeners
{
public class EventListener : IPreInsertEventListener, IPreUpdateEventListener
{
private readonly IStamper _stamper;
public EventListener() : this(new Stamper())
{
}
public EventListener(IStamper stamper)
{
_stamper = stamper;
}
public bool OnPreInsert(PreInsertEvent @event)
{
_stamper.Insert(@event.Entity as IStampedEntity, @event.State, @event.Persister);
return false;
}
public Task<bool> OnPreInsertAsync(PreInsertEvent @event, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public bool OnPreUpdate(PreUpdateEvent @event)
{
_stamper.Update(@event.Entity as IStampedEntity, @event.OldState, @event.State, @event.Persister);
return false;
}
public Task<bool> OnPreUpdateAsync(PreUpdateEvent @event, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}
然后是压模
public class Stamper : IStamper
{
private const string CreateUser = "CreateUser";
private const string CreateDate = "CreateDate";
private const string LastUpdateUser = "LastUpdateUser";
private const string LastUpdateDate = "LastUpdateDate";
public void Insert(IStampedEntity entity, object[] state, IEntityPersister persister)
{
if (entity == null)
return;
SetCreate(entity, state, persister);
SetChange(entity, state, persister);
}
public void Update(IStampedEntity entity, object[] oldState, object[] state, IEntityPersister persister)
{
if (entity == null)
return;
SetChange(entity, state, persister);
}
private void SetCreate(IStampedEntity entity, object[] state, IEntityPersister persister)
{
entity.CreateUser = GetUserName();
SetState(persister, state, CreateUser, entity.CreateUser);
entity.CreateDate = DateTime.UtcNow;
SetState(persister, state, CreateDate, entity.CreateDate);
}
private void SetChange(IStampedEntity entity, object[] state, IEntityPersister persister)
{
entity.LastUpdateUser = GetUserName();
SetState(persister, state, LastUpdateUser, entity.LastUpdateUser);
entity.LastUpdateDate = DateTime.UtcNow;
SetState(persister, state, LastUpdateDate, entity.LastUpdateDate);
}
private void SetState(IEntityPersister persister, IList<object> state, string propertyName, object value)
{
var index = GetIndex(persister, propertyName);
if (index == -1)
return;
state[index] = value;
}
private int GetIndex(IEntityPersister persister, string propertyName)
{
return Array.IndexOf(persister.PropertyNames, propertyName);
}
private string GetUserName()
{
return HttpContext.Current != null
? HttpContext.Current.User.Identity.Name
: WindowsIdentity.GetCurrent().Name;
}
}
PreInsert 将在更改刷新到数据库和事务内之前运行。您可能希望使用 PostInsert/PostUpdate 将更新发送到不同的数据库。
更新不同数据库的更好方案可能是使用服务总线通知订阅者进行了更改,然后让订阅者对外部数据库进行更改。