IPreInsertEventListener не запускается для дочерних объектов - PullRequest
0 голосов
/ 26 октября 2010

Я подключил IPreInsertEventListener и IPreUpdateEventListener для управления журналом аудита в моем приложении, которое использует NHibernate в качестве слоя ORM.

Проблема, с которой я столкнулся, заключается в том, что событие OnPreInsert() вызывается, когда объект сохраняется, но не также для каждого вставленного дочернего объекта.

В моем случае у меня есть Canine, у которого есть коллекция CanineHandlers. Что происходит, это:

  1. Создать новый Canine
  2. Создайте новый CanineHandler и добавьте его в мой недавно созданный Canine
  3. Сохранить Canine
  4. OnPreInsert запускается с только что созданными Canine и мои поля LastUpdated & LastUpdatedBy заполняются.
  5. Я получаю ошибку not-null property references a null or transient value Model.CanineHandler.LastUpdatedBy

Очевидно, проблема в том, что поля LastUpdated не заполняются до того, как NHibernate проверит экземпляр CanineHandler, но я не могу понять, как заставить NHibernate вызывать метод OnPreInsert для каждого экземпляр, который сохраняется в базе данных.

Одна из опций, с которой я играл, - это добавление другого свойства в мои Auditable POCO, которые содержат группу Auditable дочерних объектов, но с технической точки зрения я мог бы сохранить CanineHandler с измененным Canine родителем, был изменен, и тогда я буду каскадно вставлять / обновлять в противоположном направлении.

Итак, я нахожусь на правильном пути с каким-то неправильным кодом или я должен подходить к этому по-другому.

Вот соответствующий (усеченный) код:

Интерфейс Auditable

public interface IAuditable
{
    DateTime LastUpdated { get; set; }
    int? LastUpdatedBy { get; set; }
    string AuditTypeName { get; }
    Object AuditGetNew(String changes);
}

Обработчик события OnPreInsert (реализует интерфейс IPreInsertEventListener)

public bool OnPreInsert(PreInsertEvent insertEvent)
{
    if (insertEvent.Entity is IAuditable)
    {
        IAuditable auditablePoco = insertEvent.Entity as IAuditable;
        auditablePoco.LastUpdated = DateTime.Now;
        auditablePoco.LastUpdatedBy = (int?)PersonID;
        //Taken directly from Ayende's blog, these calls update the
        //event's state to match the entity's state
        Set(insertEvent.Persister, insertEvent.State, "LastUpdated", auditablePoco.LastUpdated);
        Set(insertEvent.Persister, insertEvent.State, "LastUpdatedBy", auditablePoco.LastUpdatedBy);
    }
    return false;
}

Собачье картирование

<hibernate-mapping namespace="CanineApp.Model" assembly="CanineApp.Model" xmlns="urn:nhibernate-mapping-2.2">
  <class name="Canine" table="Canine">
    <id name="CanineID" type="Int32">
      <generator class="identity" />
    </id>
    <property name="Name" type="String" length="64" not-null="true" />
    <property name="LastUpdated" type="Date" />
    <property name="LastUpdatedBy" type="Int32" />
    <set name="CanineHandlers" table="CanineHandler" inverse="true" 
        order-by="EffectiveDate desc" cascade="save-update"
        access="field.camelcase-underscore">
      <key column="CanineID" />
      <one-to-many class="CanineHandler" />
    </set>
    </class>
</hibernate-mapping>

CanineHandler mapping

<hibernate-mapping namespace="OPS.CanineApp.Model" assembly="OPS.CanineApp.Model" xmlns="urn:nhibernate-mapping-2.2">
  <class name="CanineHandler" table="CanineHandler" schema="dbo">
    <id name="CanineHandlerID" type="Int32">
      <generator class="identity" />
    </id>
    <property name="HandlerPersonID" type="Int64" precision="19" not-null="true" />
    <property name="EffectiveDate" type="DateTime" precision="16" not-null="true" />
    <property name="LastUpdated" type="Date" not-null="true" />
    <property name="LastUpdatedBy" type="Int32" not-null="true" />
    <many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" access="field.camelcase-underscore" />
  </class>
</hibernate-mapping>

1 Ответ

1 голос
/ 28 октября 2010

Не уверен, что это будет работать, но я заметил, что ваши Canine-отображения для LastUpdatedBy и LastUpdated не совпадают с CanineHandler. Возможно, попробуйте удалить not-null = "true" из сопоставлений CanineHandler.

Я выполнил аудит для nHibernate таким же образом, и он работал нормально, хотя я использовал более старый интерфейс перехвата, а именно IInterceptor. Также у меня не было not-null = "true" в моих отображениях.

CanineHandler mapping

<hibernate-mapping namespace="OPS.CanineApp.Model" assembly="OPS.CanineApp.Model" xmlns="urn:nhibernate-mapping-2.2">
  <class name="CanineHandler" table="CanineHandler" schema="dbo">
    <id name="CanineHandlerID" type="Int32">
      <generator class="identity" />
    </id>
    <property name="HandlerPersonID" type="Int64" precision="19" not-null="true" />
    <property name="EffectiveDate" type="DateTime" precision="16" not-null="true" />
    <property name="LastUpdated" type="Date"  />
    <property name="LastUpdatedBy" type="Int32"  />
    <many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" access="field.camelcase-underscore" />
  </class>
</hibernate-mapping>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...