Search code examples
c#nhibernatefluent-nhibernateautomapping

Automatically generate Created date in Fluent NHibernate Automapping


I am using Fluent NHibernate's automapping / conventions functionality to map my entities to database tables. I have this abstract class which every domain entity in my application derives itself from:

public abstract class Entity
{
    public virtual int Id { get; protected internal set; }
    public virtual DateTime Created { get; set; }
}

How can I modify my Fluent configuration so that the Created property has it's value automatically set to the value of DateTime.Now when the record is saved in the database.

Here is my Fluent configuration for reference:

private FluentNHibernate.Cfg.FluentConfiguration GetConfiguration()
{

    return Fluently
        .Configure()
        .Database(() =>
            {
                return MsSqlConfiguration.MsSql2012.ConnectionString(x => x.FromConnectionStringWithKey("main"));
            }                                     
        )
        .Mappings(
            x =>
            {
                var persistenceModel = new PersistenceModel() { ValidationEnabled = false };
                x.UsePersistenceModel(persistenceModel)
                 .AutoMappings.Add(
                    AutoMap.AssemblyOf<Entity>().Where(Exceptions.Load)
                    .Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultLazy.Never())
                    .Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultCascade.SaveUpdate())
                    .Conventions.Add(new FluentNHibernate.Conventions.Helpers.Builders.JoinConventionBuilder().Always(a => a.Fetch.Join()))
                );
            }
        )
        .ExposeConfiguration(BuildSchema);
}

Solution

  • you should use NHibernate’s event listeners for this;

    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;
        }
    
        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;
        }
    }
    

    https://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener