0

Our office team is working and ASP.NET project that uses .NET Framework 4 and NHibernate 3.3.1

I have a POCO domain class called AllResourcesInfo ( which ultimately maps to a Resource table in the database that is inner joined to some other tables, but just to keep things simple, let's just say that the AllResourcesInfo maps to the Resource table ).

I also have a POCO domain class called Section ( which ultimately maps to a Section table in the database )

I also have a POCO domain class called ResourcesInSectionBridge (which ultimately maps to a bridge table in the database called ResourcesInSectionBridge )

As the naming convention suggests, ResourcesInSectionBridge is a bridge table between the Resource and Section.

Since the ResourcesInSectionBridge contains a composite key, I created a POCO composite key identifier called ResourcesInSectionIdentifier, and also defined an Equals(object obj) method and a GetHashCode method.

When I use NHibernate Session to save a new entry for the ResourcesInSectionBridge table then I get an error:

Exception Details: System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Resources_Resou__22CA2527". The conflict occurred in database "perls", table "dbo.Resources", column 'ResourceDatabaseID'. The statement has been terminated.

The mapping for the AllResourcesInfo.hbm.xml is as follows:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
  <class name="AllResourcesInfo" table="Resources">
    <id name="ResourceDatabaseID">
      <generator class="guid" />
    </id>
    <property name="ResourceName" />
    <property name="DescriptionOfResource" />
    <property name="UserId" />
    <property name="DepartmentDatabaseID" />
    <property name="ResourceStatus" />
    <property name="isRemoved" />
    <property name="isSubmitted" />
    <property name="ResourcePlacement" />
    <property name="ResourceType" />
    <property name="ParentResourceID" />
    <joined-subclass     name="Imageitems">
      <key column="ResourceDatabaseID"/>
      <property column="DirectoryPathToFile" name="location"/>
      <property column="ImageIconPath" name="link"/>
      <property column="YearOfResource" name="YearOfResource"/>
      <property column="ArtistAuthor" name="ArtistAuthor"/>
      <property column="UploadDate" name="UploadDate"/>
      <property column="ImageitemDatabaseID" name="NativeItemDatabaseID"/>
    </joined-subclass>
    <joined-subclass     name="UriItems">
      <key column="ResourceDatabaseID"/>
      <property column="uriIconPath" name="location"/>
      <property column="UriLink" name="link"/>
      <property column="YearOfResource" name="YearOfResource"/>
      <property column="ArtistAuthor" name="ArtistAuthor"/>
      <property column="UploadDate" name="UploadDate"/>
      <property column="UriItemDatabaseID" name="NativeItemDatabaseID"/>
    </joined-subclass>
  </class>
</hibernate-mapping>

The mapping for the Section.hbm.xml is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
   <class name="Section"  table="Section">
     <id name="SectionDatabaseID">
       <generator class="guid" />
     </id>

    <many-to-one name="Courses"
   column="CourseDatabaseID" class="Courses"
  fetch="select"/>

     <many-to-one name="instructorUser" column="UserId" class="Users"
     fetch="select"/>

    <many-to-one name="term"
   column="TermDatabaseID" class="Term"
   fetch="select"/>

     <property  column="SectionCode" name="SectionCode" />

    <set name="setOfTutorials" inverse="false" lazy="true" fetch="select" >
      <key column="TutorialDatabaseID"/>
      <one-to-many class="Tutorial"/>
    </set>
  </class>
 </hibernate-mapping>

Finally, our ResourcesInSectionBridge.hbm.xml mapping file is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
  <class name="ResourcesInSectionBridge" table="ResourcesInSectionBridge"  lazy="true" >
     <composite-id name="ResourcesInSectionIdentifier" class="ResourcesInSectionIdentifier">
        <key-property name="ResourceDatabaseID" column="ResourceDatabaseID" type="Guid"  />
       <key-property name="SectionDatabaseID" column="SectionDatabaseID" type="Guid"   />
      </composite-id>

     <many-to-one name="AllResourcesInfo" class="AllResourcesInfo" cascade="none" insert="false" update="false">
       <column name="ResourceDatabaseID"></column>
       <column name="ResourceDatabaseID"></column>
     </many-to-one>
    <many-to-one name="Section" class="Section" cascade="none" insert="false" update="false">
       <column name="SectionDatabaseID"></column>
       <column name="SectionDatabaseID"></column>
     </many-to-one>
  </class>

 </hibernate-mapping>

Finally, our C# code that tries to create an entry into the ResourcesInSectionBridge table is as follows:

ResourcesInSectionBridge resInSectionBridgeEntity = new ResourcesInSectionBridge();
ResourcesInSectionIdentifier resInSectionIdentifier = new ResourcesInSectionIdentifier();
resInSectionIdentifier.ResourceDatabaseID = aSpecificResource.ResourceDatabaseID;
resInSectionIdentifier.SectionDatabaseID = sectionOfInterest.SectionDatabaseID;
resInSectionBridgeEntity.ResourcesInSectionIdentifier = resInSectionIdentifier;

resInSectionBridgeEntity.Section = sectionOfInterest;
resInSectionBridgeEntity.AllResourcesInfo = aSpecificResource;

using (ISession session = NHibernateHelper.OpenSession())
{
        session.Evict(aSpecificResource);
        session.Evict(sectionOfInterest);
        session.Clear();
        using (ITransaction transaction = session.BeginTransaction())
        {
                session.Save(resInSectionBridgeEntity);

                transaction.Commit();
        }

} // end of using (ISession session = NHibernateHelper.OpenSession())

When I use NHibernate Session to save a new entry for the ResourcesInSectionBridge table then I get an error:

Exception Details: System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Resources_Resou__22CA2527". The conflict occurred in database "perls", table "dbo.Resources", column 'ResourceDatabaseID'. The statement has been terminated.

Could you please explain why this error gets thrown? Also, could you please suggest how I could go about resolving the issue?

Sixto Saez
  • 12,610
  • 5
  • 43
  • 51
crazyTech
  • 1,379
  • 3
  • 32
  • 67

1 Answers1

2

The error you're seeing is from the database and it says that the value for ResourceDatabaseID key doesn't exist in the Resources table. Any entry made to bridge table has to be after the two source table have had their items insert if they don't already exist.

You need to properly populate both the Resource and Section entities for an insert into the bridge table to work. Look at the sample code for many-to-many mappings from these sample for something similar to what you're trying to achieve. You can download the samples without requiring their product.

Sixto Saez
  • 12,610
  • 5
  • 43
  • 51
  • Thanks Sixto, you are correct. I was inserting a Guid value of all zeroes, and it was complaining that obviously fails to exist in the one-side parent table called Resources. My pride is pushed aside LOL :) – crazyTech Jan 31 '13 at 21:50
  • 1
    BTW: If you're using SQL Server and Guid primary keys, please, please make sure that the Guid PK column is **NOT** also the clustering key. Bad things happen when you use what is effectively a random number as a basis for clustering the data. Pick another column (or columns) to create a meaningful clustering key. – Sixto Saez Jan 31 '13 at 22:03