views:

47

answers:

2

Hi,

I am trying to use NHibernate to save an object that was completely manually created. My mappings are in place and I currently have no data in the database. Everytime I call Save() or SaveOrUpdate(), NHibernate does a select statement for what I am trying to save. Then it gives me the exception: "a different object with the same identifier value was already associated with the session". Does anyone know how I can tell NHibernate to save my manually instantiated object without thinking that a different object has already been loaded?

Additional Information:

I have a primary mapping with a one-to-many collection. The exception is telling me that "a different object with the same identifier has been loaded", on the collection, not the parent object. I don't know if this provides any useful information. The mappings are as follows:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Program.Application.Models" assembly="Company.Application.Models">
  <class name="ProductVersion" table="ClientVersion" lazy="false">
    <composite-id>
      <key-property name="PracticeName">
        <column name="practiceName" not-null="true" />
      </key-property>
      <key-property name="Address">
        <column name="address" not-null="true" />
      </key-property>
      <key-property name="City">
        <column name="city" not-null="true" />
      </key-property>
      <key-property name="State">
        <column name="state" not-null="true" />
      </key-property>
      <key-property name="Zip">
        <column name="zip" not-null="true" />
      </key-property>
    </composite-id>
    <property name="LegalName" column="legalName" />
    <property name="Version" column="version" />
    <bag name="ProductsLicensesDetail" inverse="true" lazy="false" >
      <key>
        <column name="practiceName" />
        <column name="address" />
        <column name="city" />
        <column name="state" />
        <column name="zip" />
      </key>
      <one-to-many class="ProductLicenseDetail" />
    </bag>
  </class>
</hibernate-mapping>

and

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Program.Application.Models" assembly="Program.Application.Models">
  <class name="ProductLicenseDetail" table="ClientProductLicense">
    <id name="ProductCode" column="productCode">
      <generator class="assigned" />
    </id>
    <property name="TotalEnterpriseLicenses" column="totalEnterpriseLicenses" />
    <property name="EnterpriseLicensesUsed" column="enterpriseLicensesUsed" />
    <property name="TotalPracticeLicenses" column="totalPracticeLicenses" />
    <property name="PracticeLicensesUsed" column="practiceLicensesUsed" />
    <property name="TotalProviderLicenses" column="totalProviderLicenses" />
    <property name="ProviderLicensesUsed" column="providerLicensesUsed" />
    <property name="TotalUserLicenses" column="totalUserLicenses" />
    <property name="UserLicensesUsed" column="userLicensesUsed" />
    <property name="LicenseKey" column="licenseKey" />
    <property name="LicenseActivationDate" column="licenseActivationDate" />
    <property name="LicenseExpirationDate" column="licenseExpirationDate" />

    <many-to-one name="ProductVersion" class="ProductVersion" cascade="none">
      <column name="practiceName" />
      <column name="address" />
      <column name="city" />
      <column name="state" />
      <column name="zip" />
    </many-to-one>
  </class>
</hibernate-mapping>

NHibernate is telling me that "a different object with the same identifier value was already associated with the session" for the ProductCode key of the second mapping. Any insight would greatly be appreciated. Thank you.

+1  A: 

I believe you will need to add a version field to your composite key class and mapping; see this article for further details.

DanP
I believe you can set the class property optimistic-lock=false as an alternative too.
Scozzard
You are right about the version field. NHibernate In Action provides a thorough way of doing this too. I actually decided to make an assigned id based off of a hash of the fields that I considered to be composite. It seems to work. No need to use composite-id unless working with a legacy db where the schema cannot be changed.
SideFX
+1  A: 

Have you tried

session.SaveOrUpdateCopy(entity);
session.Flush();

?

Rafael Belliard

related questions