我有一堆表与通常的审计列(Created,CreatedBy,Updated,UpdatedBy)。在某些情况下,我有基表和派生表具有相同的列。不幸的是,我对此几乎没有任何治理。
在我的派生类中,我在审计属性上有new
。
我有一个实现IPreInsertEventListener
和IPreUpdateEventListener
的类。我正在使用它来设置审计字段,这似乎适用于使用继承的对象。但是,对于那些使用继承的人,审计列不会写入数据库。
以下是我的课程:
public abstract class Base : IAuditable
{
/* some other properties */
public virtual DateTime Created { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime? Updated { get; set; }
public virtual string UpdatedBy { get; set; }
public virtual string UpdateNote { get; set; }
}
public class Derived1 : Base
{
/* some other properties unique to Derived1*/
public virtual new DateTime Created { get; set; }
public virtual new string CreatedBy { get; set; }
public virtual new DateTime? Updated { get; set; }
public virtual new string UpdatedBy { get; set; }
public virtual new string UpdateNote { get; set; }
}
public class Derived2 : Base
{
/* some other properties unique to Derived2*/
public virtual new DateTime Created { get; set; }
public virtual new string CreatedBy { get; set; }
public virtual new DateTime? Updated { get; set; }
public virtual new string UpdatedBy { get; set; }
public virtual new string UpdateNote { get; set; }
}
以下是我的映射:
public class BaseMap : ClassMap<Base>
{
public BaseMap()
{
//Polymorphism.Explicit();
Schema("dbo");
Table("Base");
Id(x => x.Id)
.Column("Id")
.GeneratedBy.Identity();
#region Created / Updated
Map(x => x.Created)
.Column("Created")
.Not.Nullable();
Map(x => x.CreatedBy)
.Column("CreatedBy")
.Not.Nullable();
Map(x => x.Updated)
.Column("Updated");
Map(x => x.UpdatedBy)
.Column("UpdatedBy");
Map(x => x.UpdateNote)
.Column("UpdateNote");
#endregion
}
}
public class Derived1Map : SubclassMap<Derived1>
{
public Derived1()
{
Schema("dbo");
Table("Derived1");
KeyColumn("Id");
Map(x => x.Created)
.Column("Created")
.Not.Nullable();
Map(x => x.CreatedBy)
.Column("CreatedBy")
.Not.Nullable();
Map(x => x.Updated)
.Column("Updated");
Map(x => x.UpdatedBy)
.Column("UpdatedBy");
Map(x => x.UpdateNote)
.Column("UpdateNote");
}
}
public class Derived2Map : SubclassMap<Derived2>
{
public Derived2()
{
Schema("dbo");
Table("Derived2");
KeyColumn("Id");
Map(x => x.Created)
.Column("Created")
.Not.Nullable();
Map(x => x.CreatedBy)
.Column("CreatedBy")
.Not.Nullable();
Map(x => x.Updated)
.Column("Updated");
Map(x => x.UpdatedBy)
.Column("UpdatedBy");
Map(x => x.UpdateNote)
.Column("UpdateNote");
}
}
以下是我将监听器附加到NHibernate的方法:
.ExposeConfiguration(c =>
{
var auditor = new AuditEventListener();
c.AppendListeners(ListenerType.PreInsert, new IPreInsertEventListener[] { auditor });
c.AppendListeners(ListenerType.PreUpdate, new IPreUpdateEventListener[] { auditor });
})
这是听众:
public class AuditEventListener : IPreInsertEventListener, IPreUpdateEventListener
{
public bool OnPreInsert(PreInsertEvent @event)
{
var auditable = @event.Entity as IAuditable;
var time = DateTime.Now;
var name = Context.GetUsername();
Set(x => auditable.Created, @event.Persister, auditable, @event.State, time);
Set(x => auditable.CreatedBy, @event.Persister, auditable, @event.State, name);
return false;
}
public bool OnPreUpdate(PreUpdateEvent @event)
{
var auditable = @event.Entity as IAuditable;
var persister = @event.Persister;
var dirties = persister.FindDirty(@event.State, @event.OldState, @event.Entity, @event.Session);
var dirtyPropNames = dirties.Select(dirty => persister.PropertyNames[dirty]).ToList();
var time = DateTime.Now;
var name = Context.GetUsername();
var note = "Updated " + string.Join(",", dirtyPropNames);
Set(x => auditable.Updated, persister, auditable, @event.State, time);
Set(x => auditable.UpdatedBy, persister, auditable, @event.State, name);
Set(x => auditable.UpdateNote, persister, auditable, @event.State, note);
return false;
}
private void Set<T, U>(Expression<Func<U, T>> expression, IEntityPersister persister, U instance, object[] state, T value)
{
var member = expression.Body as MemberExpression;
if (member != null)
{
var index = Array.IndexOf(persister.PropertyNames, member.Member.Name);
if (index == -1)
{
return;
}
state[index] = value;
var property = (member.Member as PropertyInfo);
if (property != null)
{
property.SetValue(instance, value, null);
}
}
}
}