These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Joined subclass loads collection with incorrect foreign key
PostPosted: Tue May 27, 2008 8:19 am 
Newbie

Joined: Tue May 27, 2008 4:17 am
Posts: 1
Location: Crawley, UK
I am involved in a project migrating our custom DAL layer over to NHibernate. I'm having a problem with regards to the SQL my NHibernate mapping files are generating.

I have an inheritance hierarchy of three classes, which maps to two tables as a <joined-subclass>. The lowest level child class has a collection that maps to another table, as a <bag>. See below for full details.

The issue is the SQL NHibernate creates selects the collection using the wrong key from the parent associated object.

Any help greatly appreciated

Hibernate version:
Quote:
NHibernate 1.2.1.4000


Mapping documents:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
  xmlns="urn:nhibernate-mapping-2.2"
  default-cascade="none"
  auto-import="true"
  namespace="BakerTilly.CompositeReporting.Domain.Entities"
  assembly="BakerTilly.CompositeReporting.Domain.Entities">

  <class name="Entity`1[[BakerTilly.CompositeReporting.Domain.Entities.Organisation]]" table="Entity" lazy="false">
    <id name="EntityID" column="ID" type="Int32" unsaved-value="-1">
      <generator class="identity" />
    </id>
    <property name="EntityType" column="EntityTypeID"  />
    <joined-subclass name="Organisation" table="Organisation" lazy="false">
      <key column="EntityID" ></key>
      <property name="Id" column="ID" generated="always" />
      <property name="ParentID" column="ParentID" />
      <property name="Name" column="Name"  />
      <property name="FullName" column="FullName" />
      <property name="Code" column="Code"  />
      <property name="CurrencyID" column="CurrencyID" />
      <property name="Editable" column="Editable" />
      <property name="AccountsYearEnd" column="AccountsYearEnd" />
      <property name="Sector" column="SectorID" />
      <property name="ImportType" column="ImportTypeID" />
      <property name="EntityID" column="EntityID" />
      <property name="Theme" column="Theme" />
     
      <bag name="Attributes" table="OrganisationAttribute" lazy="false" cascade="all" fetch="select">
        <key column="OrganisationID" foreign-key="OrganisationID"></key>
        <one-to-many class="OrganisationAttribute"></one-to-many>
      </bag>
     
      </joined-subclass>
  </class>

</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
  xmlns="urn:nhibernate-mapping-2.2"
  default-cascade="none"
  auto-import="true"
  namespace="BakerTilly.CompositeReporting.Domain.Entities" assembly="BakerTilly.CompositeReporting.Domain.Entities">

  <class  name="OrganisationAttribute" table="OrganisationAttribute" lazy="false">
    <id name="Id">
      <generator class="native"/>
    </id>   
    <property name="OrganisationId"></property>
    <property name="Name"></property>
    <property name="Ordinal"></property>   
  </class>

</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

Code:
            ISession session = NHibernateHelper.GetCurrentSession();

            ICriteria criteria = session.CreateCriteria(typeof(Organisation));
            criteria.Add(Expression.Eq("Id", organisationID));
            IOrganisation org = criteria.UniqueResult<IOrganisation>();

            NHibernateHelper.CloseSession();




Full stack trace of any exception that occurs:
None occuring

Name and version of the database you are using:
SQL Server 2008 Stadard Edition

The generated SQL (show_sql=true):
This is grabbed from SQL Query Profiler.
In the first query 17 is the primary key of the row from the Organisation table
In the second query 32 is the primary key of the row from the Entity table, but I really want to pass in 17 as this is the foreign key value


Code:
exec sp_executesql N'SELECT this_.EntityID as ID2_0_, this_.ID as ID3_0_, this_.ParentID as ParentID3_0_, this_.Name as Name3_0_, this_.FullName as FullName3_0_, this_.Code
as Code3_0_, this_.CurrencyID as CurrencyID3_0_, this_.Editable as Editable3_0_, this_.AccountsYearEnd as Accounts9_3_0_, this_.SectorID as SectorID3_0_, this_.ImportTypeID
as ImportT11_3_0_, this_.EntityID as EntityID3_0_, this_.Theme as Theme3_0_, this_1_.EntityTypeID as EntityTy2_2_0_ FROM Organisation this_ inner join Entity this_1_ on
this_.EntityID=this_1_.ID WHERE this_.ID = @p0',N'@p0 int',@p0=17

exec sp_executesql N'SELECT attributes0_.OrganisationID as Organisa5___1_, attributes0_.Id as Id1_, attributes0_.Id as Id1_0_, attributes0_.OrganisationId as
Organisa2_1_0_, attributes0_.Name as Name1_0_, attributes0_.Ordinal as Ordinal1_0_ FROM OrganisationAttribute attributes0_ WHERE attributes0_.OrganisationID=@p0',N'@p0
int',@p0=32


C# Code

Code:
using System;
using System.Collections.Generic;

namespace BakerTilly.CompositeReporting.Domain.Entities
{
    /// <summary>
    /// Contains all the information for an Organisation
    /// </summary>
    [Serializable]
    public class Organisation : Entity<Organisation>, IOrganisation
    {
        private int parentID;
        private string name;
        private string fullName;
        private string code;
        private int currencyID;
        private bool editable;
        private DateTime accountsYearEnd;
        private Sector sector;
        private ImportType importType;
        private string theme;
        //private OrganisationAttributeCollection attributes;
        private IList<OrganisationAttribute> attributes;
        private OrganisationAttributeUsageCollection attributeUsage;

        /// <summary>
        /// Initializes a new instance of the <see cref="Organisation"/> class.
        /// </summary>
        public Organisation()
        {
        }

        /// <summary>
        /// Gets the type of the entity.
        /// </summary>
        /// <value>The type of the entity.</value>
        public override EntityTypes EntityType { get; set; }

        /// <summary>
        /// Gets or sets the parent ID.
        /// </summary>
        /// <value>The parent ID.</value>
        public int ParentID
        {
            get { return this.parentID; }
            set { this.parentID = value; }
        }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        /// <summary>
        /// Gets or sets the full name.
        /// </summary>
        /// <value>The full name.</value>
        public string FullName
        {
            get { return this.fullName; }
            set { this.fullName = value; }
        }

        /// <summary>
        /// Gets the type.
        /// </summary>
        /// <value>The type.</value>
        public OrganisationType Type
        {
            get
            {
                if (this.parentID > 0)
                {
                    return OrganisationType.Child;
                }
                else
                {
                    return OrganisationType.Parent;
                }
            }
        }

        /// <summary>
        /// Gets or sets the currency ID.
        /// </summary>
        /// <value>The currency ID.</value>
        public int CurrencyID
        {
            get { return this.currencyID; }
            set { this.currencyID = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="Organisation"/> is editable.
        /// </summary>
        /// <value><c>true</c> if editable; otherwise, <c>false</c>.</value>
        public bool Editable
        {
            get { return this.editable; }
            set { this.editable = value; }
        }

        /// <summary>
        /// Gets or sets the accounts year end.
        /// </summary>
        /// <value>The accounts year end.</value>
        public DateTime AccountsYearEnd
        {
            get {return this.accountsYearEnd ;}
            set { this.accountsYearEnd = value; }
        }

        /// <summary>
        /// Gets or sets the sector.
        /// </summary>
        /// <value>The sector.</value>
        public Sector Sector
        {
            get { return this.sector; }
            set { this.sector = value; }
        }

        /// <summary>
        /// Gets or sets the type of the import.
        /// </summary>
        /// <value>The type of the import.</value>
        public ImportType ImportType
        {
            get { return this.importType; }
            set { this.importType = value; }
        }

        /// <summary>
        /// Gets or sets the theme.
        /// </summary>
        /// <value>The theme.</value>
        public string Theme
        {
            get { return this.theme; }
            set { this.theme = value; }
        }

        /// <summary>
        /// Gets or sets the code.
        /// </summary>
        /// <value>The code.</value>
        public string Code
        {
            get { return this.code; }
            set { this.code = value; }
        }

        /// <summary>
        /// Gets or sets the attributes.
        /// </summary>
        /// <value>The attributes.</value>
        public IList<OrganisationAttribute> Attributes
        {
            get { return this.attributes; }
            set { this.attributes = value; }
        }

        /// <summary>
        /// Gets or sets the attribute usage.
        /// </summary>
        /// <value>The attribute usage.</value>
        public OrganisationAttributeUsageCollection AttributeUsage
        {
            get { return this.attributeUsage; }
            set { this.attributeUsage = value; }
        }
    }

    /// <summary>
    /// Contains all the information for an Entity
    /// Read Entity as Contactable Entity
    /// </summary>
    [Serializable]
    public abstract class Entity<EntityT> : BaseDomainEntity<EntityT>, BakerTilly.CompositeReporting.Domain.IEntity
    {
        private int entityID;
        private ContactDetailCollection contactDetails;

        /// <summary>
        /// Gets the type of the entity.
        /// </summary>
        /// <value>The type of the entity.</value>
        public abstract EntityTypes EntityType { get; set; }

        /// <summary>
        /// Gets or sets the entity ID.
        /// </summary>
        /// <value>The entity ID.</value>
        public int EntityID
        {
            get { return this.entityID; }
            set { this.entityID = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Entity&lt;EntityT&gt;"/> class.
        /// </summary>
        public Entity()
        {
        }

    /// <summary>
    /// The base class for all domain entity objects
    /// </summary>
    /// <typeparam name="TDomainEntity">The type of the domain entity.</typeparam>
    [Serializable]
    public abstract class BaseDomainEntity<TDomainEntity>
    {
        private int id;
        private RecordStatus recordStatus;


        /// <summary>
        /// Default class constructor
        /// </summary>
        protected BaseDomainEntity()
        {
            this.id = DomainEntityConstants.NullIdInt32Value;
            this.recordStatus = RecordStatus.Available;
        }
}


Class diagram

Image

Database diagram

Image

Database data

Image


Top
 Profile  
 
 Post subject: Bump
PostPosted: Mon Feb 16, 2009 4:27 pm 
Newbie

Joined: Sun Feb 15, 2009 10:36 pm
Posts: 2
I'm bumping this because it appears to describe the exact same issue I posted about here


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.