views:

213

answers:

1

I have the following mapping, the many-to-one property 'Message' has a corresponding one-to-many association in the 'RootMessage' class.

<class name="IMessageReceipt" lazy="false" table="MessageReceipts" abstract="true">

     <id name="Id">
      <generator class="guid.comb"></generator>
     </id>

     <discriminator column="Discriminator"/>
     <property name="Address" />
     <property name="Status" />
     <property name="MarkedAsDeleted" />

     <many-to-one name="Message" column="MessageId" class="RootMessage" 
                not-found="ignore"/>

     <subclass name="MessageReceipt" lazy="false" discriminator-value="1">
     </subclass>

    </class>

The many-to-one association refuses to load when using the criteria api (all I get is NULL), here is an example of a query:

      List<IMessageReceipt> list;
  using (var tx = Session.BeginTransaction())
  {
   var criteria = Session.CreateCriteria(typeof (IMessageReceipt));
   criteria.Add(Restrictions.Eq("Address", address));
   criteria.Add(Restrictions.Eq("Status", status));
   criteria.SetFirstResult(0);
   criteria.SetMaxResults(quantity);
   list = criteria.List<IMessageReceipt>().ToList();
   tx.Commit();
  }
  return list;

Any ideas?

+1  A: 

Ok so after almost a day of chagrin I have the solution. NHibernate doesn't automatically assume a bi-directional association between two entities even if you have mappings between both. You need to imperatively declare the associations in your code before persisting. Thus:

message.Receipts = receipts;
foreach (var receipt in receipts)
{
   receipt.Message = message;
}
Session.Save(message);
tx.Commit();

Also inverse="true" should be applied to the side with the collection member:

<set name="Receipts" inverse="true" cascade="save-update">
<key column="MessageId"></key>
<one-to-many class="IMessageReceipt"/>
</set>
rjarmstrong