How to use NHibernate features to audit transactions to database?
I am going to list some steps, which you can follow to enable NHibernate auditing:

  1. Not all entities require auditing, and to distinguish entities that require auditing, we will create an abstract class which all auditable entites are going to inherit from. Let's call the class "AuditableEntity"
  2. public abstract class AuditableEntity
    {
        public DateTime CreateDateTime {get; set;}
        public DateTime UpdateDateTime {get; set;}
        public string CreateUserName {get; set;}
        public string UpdateUSerName {get;set;}
    }


  3. Create a base mapping for the AuditableEntity (assuming database field names, match the class property names)
  4. public class AuditableEntityMapping : ClassMap : where T : AuditableEntity
    {
        public AuditableEntityMapping()
        {
            Map(x => x.CreateDateTime);
            Map(x => x.UpdateDateTime);
            Map(x => x.CreateUserName);
            Map(x => x.UpdateUserName);
        }
    }

  5. Now, every entity we want to audit, we just have to inherit the entity from AuditableEntity, like the following
  6. public class Product : AuditableEntity
    {
        public string Name {get; set; }
        public string ProductNumber {get; set;}
    }
    
    public class ProductMapping : AuditableEntityMapping
    {
        public ProductMapping () : base() 
        {
            Map(x => x.Name);
            Map(x => x.ProductNumber);
        }
    }

  7. Next, how to do automatic auditing from NHibernate?
  8. NHibernate allows us to hook up with its event, like update/create events
    So, we are going to write an "Event Listener" to listen to the update and insert statement, and inject our code that update the auditing fields.
    The following code will do just that:
    public class AuditEventListener : IPreUpdateEventListener, IPreInsertEventListener
    {
        public bool OnPreInsert(PreInsertEvent @event)
        {
            var audit = @event.Entity as AuditableEntity;
            if (audit == null)
                return false;
            var date = SystemTime.Now();
            Set(@event.Persister, @event.State, "ModifiedDate", date);
            audit.ModifiedDate = date;
            return false;
        }
        
        public bool OnPreUpdate(PreUpdateEvent @event)
        {
            var audit = @event.Entity as AuditableEntity;
            if (audit == null)
                return false;
            var date = SystemTime.Now();
            Set(@event.Persister, @event.State, "ModifiedDate", date);
            audit.ModifiedDate = date;
            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;
        }
    }

  9. Finally, we want to hook up that event listener with NHibernate initialization.
  10. The following Fluent-configuration will do that 
    var cfg = new ConfigurationBuilder().Build();
    var nhConfig = Fluently.Configure(cfg);
    
    nhConfig.Mappings(m => m.FluentMappings.AddFromAssemblyOf())
        .ExposeConfiguration(x => x.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[] { new AuditEventListener()})
        .ExposeConfiguration(x => x.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new AuditEventListener()})
        .BuildConfiguration();
    SessionFactory = nhConfig.BuildSessionFactory();