Question

I recently have found out how to audit instances with the IPreDeleteEventListener, IPreInsertEventListener and IPreUpdateEventListener in the NHibernate.Event namespace.

However, it still confuses me what shall these event return either on successful or unsuccessful finality.

For example, let's take a look at Ayende's blog article found here:

Following his example, one could implement the interfaces as following:

public class AuditEventListener : IPreInsertEventListener {
    public bool OnPreInsert(OnPreInsert @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, "CreatedBy", name);

        audit.CreatedAt = time;
        audit.CreatedBy = name;

        return false;
    }
}

What odes it actually mean to return either true or false as return value, since I have another example where true is returned instead of false as Ayende wrote.

Which seems to return true instead of false.

public class SoftDeletableListener : IPreDeleteEventListener {
    public void Register(Configuration cfg) {
        cfg.EventListeners.PreDeleteEventListeners = 
            new IPreDeleteEventListener[] { this }
                .Concat(cfg.EventListeners.PreDeleteEventListeners)
                .ToArray();
    }

    public Boolean OnPreDelete(PreDeleteEvent @event) {
        ISoftDeletable softDeletable = @event.Entity as ISoftDeletable;

        if (softDeletable == null) return true;

        EntityEntry entry = @event.Session
            .GetSessionImplementation()
            .PersistenceContext
            .GetEntry(@event.Entity);
        entry.Status = Status.Loaded;

        softDeletable.Deleted = true;

        Object id = @event.Persister
            .GetIdentifier(@event.Entity, @event.Session.EntityMode);
        Object [] fields = @event.Persister
            .GetPropertyValues(@event.Entity, @event.Session.EntityMode);
        Object version = @event.Persister
            .GetVersion(@event.Entity, @event.Session.EntityMode);

        @event.Persister.Update(id
            , fields
            , new Int32[1]
            , false
            , fields
            , version
            , @event.Entity
            , null
            , @event.Session.GetSessionImplementation());

        return true;
    }
}

So I wonder, what false/true actually tells NHibernate depending on the listener dealt with.

Was it helpful?

Solution

The returned value in this case should be enum, Let's use the name OnPreEventResult, and these would be the possible values:

  • OnPreEventResult.Continue => to continue currently return false
  • OnPreEventResult.Break => at the moment, when the true is returned the Action is aborted

So, as both examples above show, we can use the return value to manage the execution flow:

  1. to Continue:
    If we in the AuditEventListener return false, we in fact return something like OnPreEventResult.Continue. We've made some custome logic, and we want NHibernate to continue... so the false is returned

  2. to Break/Abort:
    Ayende's example is showing us how to change the real DELETE into UPDATE. Update is called explicitly @event.Persister.Update(... and the delete is not executed due to the returned value true, i.e. OnPreEventResult.Break

In the code, the returned values are stored in local variable called veto, which is again more self descriptive.

See:

A snippet from the EntityInsertAction, the Execute() method:

...
bool veto = PreInsert();

if (!veto)
{    
    persister.Insert(id, state, instance, Session);
...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top