NHibernate IPreUpdateEventListener, IPreInsertEventListener not saving to DB

前端 未结 1 675
萌比男神i
萌比男神i 2021-01-25 03:56

I\'m trying to implement simple auditing on my entities. Auditable entities implement the ITimestampable interface which defines DateAdded and Da

相关标签:
1条回答
  • 2021-01-25 04:47

    The answer would be hidden/revealed in this cites from Ayende's article

    • NHibernate IPreUpdateEventListener & IPreInsertEventListener

    ...Here comes the subtlety, however. We cannot just update the entity state. The reason for that is quite simple, the entity state was extracted from the entity and place in the entity state, any change that we make to the entity state would not be reflected in the entity itself. That may cause the database row and the entity instance to go out of sync, and make cause a whole bunch of really nasty problems that you wouldn’t know where to begin debugging.

    You have to update both the entity and the entity state in these two event listeners (this is not necessarily the case in other listeners, by the way). Here is a simple example of using these event listeners:

    This is the code showing how to, from the same article:

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

    And here is the magical Set()

    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;
    }
    
    0 讨论(0)
提交回复
热议问题