We are using NHibernate on our project and we are hooking into the pre update/insert/delete events to do some auditing.
We want to audit each entity to its own audit table that has the same schema as the source table (maybe with an audit operation such as "Update", "Insert" etc).
I have looked at the unHAddins that will generate triggers automatically but it seems to drop and recreate the audit tables when you make a change to the main table which we cannot accept, we also need to have some custom logic such that we will only audit the record under certain circumstances of its actual properties (the properties we care about are part of the base class for all of our objects).
To do this simply I figured that I can just extend our existing domain classes and then define a new Nhibernate mapping for those extended classes.
For example:
We have a class Instrument
public class Instrument : BaseObject, IAuditable
{
public virtual string Title { get; set; }
public virtual IList<Control> Controls { get; set; }
public virtual CouncilRegion Region { get; set; }
public Type GetAuditType()
{
return typeof (InstrumentAudit);
}
I have defined an interface Iauditable so that we can find out what class is the auditing class for any Iauditable object.
The auditing class is as follows
public class InstrumentAudit : Instrument
{}
It has no additional functionality in it it is basically a hack to let us map it to our audit table in NHibernate.
So this seems like it would work but the problem actually comes in when trying to handle the NHibernate events
public class EventListener: IPreInsertEventListener, IPreUpdateEventListener, IPreDeleteEventListener
{
private readonly IAuditLogger _logger = new AuditLogger();
public bool OnPreInsert(PreInsertEvent e)
{
Audit(e.Entity as BaseObject, AuditType.Insert);
return false;
}
}
private void Audit(object entity, AuditType auditType)
{
if(entity is IAuditable && entity is BaseObject)
{
_logger.Log(entity, auditType);
}
}
The e.Entity is given to me as an Object.
public class AuditLogger : IAuditLogger
{
public void Log(object entity, AuditType auditType)
{
if (entity is IAuditable && entity is BaseObject)
{
var auditObject = entity as IAuditable;
Type type = auditObject.GetAuditType();
var x = (type) auditObject;
DataRepository.Instance.Save(x);
}
}
}
Above is the code I would like to work, basically I know that the object is one that should be audited and it is one of my base objects, so I would like to convert it to the subtype of the audit object and pass it to nhibernate to save.
Unfortunately it doesn't seem like you can cast to a variable it has to be an actual type, is there anyway around this so I can cast or convert the object to its "audit" type without having to put constructors/convertors for each audit type that takes its base type and saves the properties?