Что false/true на самом деле означает для IPreInsertEventListeners?

Недавно я узнал, как проводить аудит экземпляров с IPreDeleteEventListener, IPreInsertEventListener и IPreUpdateEventListener в пространстве имен NHibernate.Event.

Тем не менее, меня все еще смущает, что вернут эти события в случае успешного или неудачного финала.

Например, давайте взглянем на статью в блоге Айенде, найденную здесь:

Следуя его примеру, можно было бы реализовать интерфейсы следующим образом:

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

Что на самом деле означает возвращать true или false в качестве возвращаемого значения, поскольку у меня есть другой пример, где true возвращается вместо false, как писал Айенде.

Который, кажется, возвращает true вместо 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;
    }
}

Поэтому мне интересно, что false/true на самом деле сообщает NHibernate в зависимости от слушателя, с которым имеет дело.


person Will Marcouiller    schedule 17.02.2014    source источник
comment
В примере SoftDeletableListener не должно быть if (softDeletable == null) return false; (false вместо true)? В противном случае никакая сущность не будет удалена, будь то ISoftDeletable или нет.   -  person lalibi    schedule 06.07.2016


Ответы (1)


Возвращаемое значение в этом случае должно быть enum. Давайте использовать имя OnPreEventResult, и это будут возможные значения:

  • OnPreEventResult.Continue => чтобы продолжить в настоящее время вернуть false
  • OnPreEventResult.Break => в момент возврата true Действие прервано

Итак, как показывают оба приведенных выше примера, мы можем использовать возвращаемое значение для управления потоком выполнения:

  1. Продолжить:
    Если мы в AuditEventListener возвращаем false, мы на самом деле возвращаем что-то вроде OnPreEventResult.Continue. Мы сделали некоторую пользовательскую логику и хотим, чтобы NHibernate продолжал работать... поэтому возвращается false

  2. прервать/прервать:
    пример Айенде показывает нам, как заменить настоящий DELETE на UPDATE. Обновление вызывается явно @event.Persister.Update(..., а удаление не выполняется из-за возвращаемого значения true, т. е. OnPreEventResult.Break

В коде возвращаемые значения сохраняются в локальной переменной с именем veto, что опять-таки более информативно.

Видеть:

Фрагмент из метода EntityInsertAction, Execute():

...
bool veto = PreInsert();

if (!veto)
{    
    persister.Insert(id, state, instance, Session);
...
person Radim Köhler    schedule 18.02.2014
comment
+1 Спасибо за это отличное объяснение! Теперь я лучше понимаю, что происходит. Эти примеры, ИМХО, были бы намного более чистым кодом, если бы они действительно использовали это перечисление OnPreventResult. Спасибо @Radim! - person Will Marcouiller; 18.02.2014
comment
Отлично, если это хоть как-то помогло. Наслаждайтесь NHibernate :) - person Radim Köhler; 18.02.2014
comment
Отличное объяснение. На самом деле пример неверный. Если класс не реализует контракт Soft Delete, перехватчик должен возвращать false, а не true. - person Raffaeu; 06.12.2017