Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate Error - Save the Transient Instance Before Flushing

I had successfully written a system that contained an order with child order lines, using cascade updates from the order to save the order lines. In the next iteration I want to associate the order lines with a despatch class. This seemed quite straight forward - add a nullable DespatchID column to the order line table as a foriegn key to the Despatch table. However, when I add this to the mapping and save the order object with the despatches not set on the order lines, I get the error "object references an unsaved transient instance - save the transient instance before flushing".

If I remove the association between the order line and the despatch, it saves OK. I can only presume that the error is caused because it is trying to save the despatch, which does not exist.

Here are the mappings (the order lines class is called OrderProductAmount):

  <class name="NHS.WebTeam.PandemicFluDistribution.Order, NHS.WebTeam.PandemicFluDistribution" table="[Order]" lazy="false" optimistic-lock="version" where="Deleted=0" >
    <id name="ID" type="Int32" column="OrderID" unsaved-value="0">
      <generator class="hilo">
        <param name="table">NHibernateHiLo</param>
        <param name="column">NextValue</param>
        <param name="max_lo">100</param>
      </generator>
    </id>

    <version column="version" name="Version"/>
    <property name="Deleted" column="Deleted" />

    <property name="DateEntered"></property>
    <property name="RequiredDeliveryDate"></property>

    <many-to-one name="Practice" column="PracticeID"></many-to-one>

    <set name="OrderProductAmounts" access="field.camelcase-underscore" inverse="true" cascade="all-delete-orphan" lazy="true">
      <key column="OrderID"></key>
      <one-to-many class="NHS.WebTeam.PandemicFluDistribution.OrderProductAmount, PandemicFluDistribution" />
    </set>

  </class>

  <class name="NHS.WebTeam.PandemicFluDistribution.OrderProductAmount, NHS.WebTeam.PandemicFluDistribution" table="OrderProductAmount" lazy="false" optimistic-lock="version" where="Deleted=0" >
    <id name="ID" type="Int32" column="OrderProductAmountID" unsaved-value="0">
      <generator class="hilo">
        <param name="table">NHibernateHiLo</param>
        <param name="column">NextValue</param>
        <param name="max_lo">100</param>
      </generator>
    </id>

    <version column="version" name="Version"/>
    <property name="Deleted" column="Deleted" />

    <many-to-one name="Order" column="OrderID"></many-to-one>
    <many-to-one name="ProductAmount" column="ProductAmountID"></many-to-one>
    <many-to-one name="Despatch" column="DespatchID" cascade="none" not-null="false"></many-to-one>
  </class>

  <class name="NHS.WebTeam.PandemicFluDistribution.Despatch, NHS.WebTeam.PandemicFluDistribution" table="Despatch" lazy="false" optimistic-lock="version" where="Deleted=0" >
    <id name="ID" type="Int32" column="DespatchID" unsaved-value="0">
      <generator class="hilo">
        <param name="table">NHibernateHiLo</param>
        <param name="column">NextValue</param>
        <param name="max_lo">100</param>
      </generator>
    </id>

    <version column="version" name="Version"/>
    <property name="Deleted" column="Deleted" />

    <property name="DateDespatched"></property>
    <property name="RequiredDeliveryDate"></property>

    <many-to-one name="Practice" column="PracticeID"></many-to-one>

    <set name="OrderProductAmounts" access="field.camelcase-underscore" inverse="true" cascade="none" lazy="true">
      <key column="DespatchID"></key>
      <one-to-many class="NHS.WebTeam.PandemicFluDistribution.OrderProductAmount, PandemicFluDistribution" />
    </set>

  </class>

The code to create the order is essentially this:

Dim practice = ... get relevant Practice ...
Dim productAmount = ... get relevant ProductAmount ...
Dim newOrder as Order = new Order(practice)
newOrder.AddProductAmount(new OrderProductAmount(newOrder, productAmount)
OrderDAO.Save(newOrder)

Does anybody have any ideas?

like image 555
Richard Bramley Avatar asked Nov 03 '09 12:11

Richard Bramley


1 Answers

As implied by the comments above (for which a big thanks), there was something that didn't sound right about the Despatch. And, as it turned out, the Despatch was not the problem. Although for some reason it worked before I added it.

I resolved the problem by adding a cascade="all" to the OrderProductAmount link to the Order:

<many-to-one name="Order" column="OrderID" cascade="all"></many-to-one>

The error that was thrown was that the Order was still transient when the OrderProductAmount was being saved. This is very confusing since it is the Order and not the OrderProductAmount that I am saving - the OrderProductAmounts are only saved through a cascade from the Order.

So, if anybody has any ideas why this might be, I'd be interested to know.

like image 116
Richard Bramley Avatar answered Oct 23 '22 04:10

Richard Bramley