views:

110

answers:

3

When I save a new Report, NHibernate inserts the Report, ignores the Publication and tries to insert the UserPublication. However SQL then complains about violation of FK constraint. Its like NHibernate doesn't think the Publication is new even though the row doesn't exist in the db.

Think of the entity relationship as: A Report can have many Publications (Publications belong to a Report) A Publication can have many UserPublications (UserPublications belong to a Publication)

Any ideas what I've done wrong? Thanks in advance.

Here's the mappings:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Model.Report, Model" table="Report" lazy="true">
  <id name="Id" access="property" column="ReportID">
    <generator class="assigned"></generator>
  </id>    
  <property name="DeleteUnread" access="property" />
  <property name="Description" access="property" />
  <property name="Name" access="property" />    
  <bag name="Publications" access="property" lazy="true" cascade="all-delete-orphan">
    <key column="ReportID"/>
    <one-to-many class="Model.Publication, Model"/>        
  </bag>
</class>  
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class name="Model.Publication, Model" table="Publication" lazy="true">
    <id name="Id" access="property" column="PublicationID">    
      <generator class="assigned"></generator>
    </id>  
    <property name="CreatedOn" access="property" />
    <property name="FileExtension" access="property" /> 
    <property name="IsDownloaded" access="property" />
    <property name="ToBeDownloaded" access="property" />
    <property name="Name" access="property"/>  
    <bag name="UserPublications" access="property" lazy="true" cascade="all-delete-orphan">    
      <key column="PublicationID"></key>
      <one-to-many class="Model.UserPublication, Model" />
    </bag>
    <many-to-one name="Report" class="Model.Report, Model" lazy="false" column="ReportID" not-null="true" cascade="none">
    </many-to-one>
  </class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class name="Model.UserPublication, Model" table="UserPublication" lazy="true">
    <id name="Id" access="property" column="UserPublicationID">
      <generator class="native"></generator>
    </id>
    <property name="IsFlaggedForDeletion" access="property" column="IsFlaggedForDeletion" />
    <property name="HasBeenRead" access="property" column="HasBeenRead" />
    <property name="DateReceived" access="property" column="DateReceived" />
    <property name="MustRead" access="property" column="MustRead" />
    <property name="ShowToolbar" access="property" column="ShowToolbar" />
    <property name="MaxAge" access="property" column="MaxAge" />
    <property name="FeedId" access="property" column="FeedId" />
    <property name="CanEdit" access="property" column="CanEdit" />    
    <many-to-one name="User" access="property" column="ClientUserID" class="Model.ClientUser, Model" not-null="true" cascade="none">      
    </many-to-one>
    <many-to-one name="Publication" access="property" class="Model.Publication, Model" column="PublicationID" not-null="true" cascade="none">      
    </many-to-one>
</class>

A: 

I think the problem is that id of publications is an assigned id therefore NHibernate can't recognize when it should insert a publication. When you flush a session it first insert all inserted objects , then it updates all updated objects and then deletes all deleted objects. So I think that's going to happen here: You save a Report that has publications that have userpublications.Since publication id is assigned NHibernate assumes it has to be updated and ignore it but UserPublication id is native and NHibernates knows when it should be inserted and tries to insert it thus a FK violation happens. To solve this problem you can add a version property to publication so NHibernate can insert it based on its version value.

Beatles1692
Yes what you say makes complete sense. However I used a different way to fix instead of using version. As shown below.
empo
Thanks for your comment btw.
empo
I'm not sure if this solution is going to work if you want to update a Publication because in this case NHibernate takes all given ids as unsaved and I don't know what happens if a publication exists
Beatles1692
A: 

The UserPublications bag in the Publication class has a wrong key element. It should be:

<key column="PublicationID"/>
Jan Willem B
Well spotted :-)
empo
A: 

This works. I set the unsaved-value attribute to "any".

I don't think there will be any repurcussions.

<id name="Id" access="property" column="PublicationID" unsaved-value="any">    
  <generator class="assigned"></generator>
</id>
empo