IPreInsertEventListener不为子对象触发

时间:2010-10-26 18:06:54

标签: c# nhibernate events orm

我已经连接了IPreInsertEventListenerIPreUpdateEventListener来管理我的应用中的审核日志记录,它使用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
  6. 显然问题是在NHibernate验证LastUpdated实例之前没有填充CanineHandler字段,但我无法弄清楚如何让NHibernate调用{{ 1}}用于持久保存到数据库的每个实例的方法。

    我玩过的一个选项是在我的OnPreInsert POCO中添加另一个属性,其中包含一组Auditable个子对象,但从技术上讲,我可以保存一个Auditable修改后的CanineHandler父级已被更改,然后我将以相反的方向级联插入/更新。

    那么,我是否在某个地方使用了一些不正确的代码,或者我应该以不同的方式接近它。

    这是相关的(截断的)代码:

    可审计界面

    Canine

    OnPreInsert事件处理程序(实现IPreInsertEventListener接口)

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

    犬类制图

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

    CanineHandler映射

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

1 个答案:

答案 0 :(得分:1)

不确定这会有效,但我注意到LastUpdatedBy和LastUpdated的Canine映射与CanineHandler的不同。也许尝试从CanineHandler映射中删除not-null =“true”。

我已经以相同的方式对nHibernate进行了审计,虽然我使用了较旧的拦截界面,即IInterceptor,但它运行良好。我的映射中也没有not-null =“true”。

CanineHandler映射

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