NHIbernate: Mapping Audit user
On every object in my DB, I hav开发者_开发问答e audit fields for CreatedBy, CreatedOn, ModifiedOn, and ModifiedBy. the CreatedBy and ModifiedBy map to a User object that I have created to map to my users table. I was originally storing the UserId (Primary key) in those fields and everything mapped fine with a mapping definition of
<many-to-one name="CreatedBy" column="CreatedBy" lazy="proxy"></many-to-one>
.
However, I want to switch those fields to store the username instead but I can't find how to load the persistent User entity from the non-primary-key field. I've looked into IUserTypes, ICompositeUserType, event listeners, and some other random things, but I can't seem to get anything completely working.
As of right now I've added a CreatedByName and ModifiedByName field that stores the username while the original fields still store the ID (did this when playing around with CompositeUserType), so I have both ID and username that I can utilize if needed.
This seems like something that should be common enough that there should be a solution, but I can't find anything.
You can specify the property-ref
attribute in your many-to-one
to specify an arbitrary join property.
http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-manytoone
Since auditing is not a business concern, I have found the best way to solve this is to use NHibernate event listeners.
A sample listener might look like this:
namespace ADT.Data.Repositories.NHibernate.EventListeners
{
public class PreInsertEventListener : IPreInsertEventListener
{
public bool OnPreInsert(PreInsertEvent @event)
{
var audit = @event.Entity as IHaveAuditInformation;
if (audit == null)
return false;
var time = DateTime.Now;
var user = Security.GetLoggedInUser();
Set(@event.Persister, @event.State, "LogDate", time);
Set(@event.Persister, @event.State, "User", user);
audit.LogDate = time;
audit.User = user;
return false;
}
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;
}
}
}
I log the user and the date the entity was inserted. There is also a preupdate listener. Of course, you'd have to configure the listeners with NHibernate Configuration.
精彩评论