When using an inverted one-to-many in a "Table per subclass using discriminator" inheritance hierarchy; nHibernate looks for the many-to-one back-reference on the table mapped to the base class instead of on the derived class' table.
In the mapping below Employer.Employees is implemented using a FK on the Employees table. The generated SQL looks for EmployerId on Person (employees0_) instead of Employee (employees0_1_). [Highlighted in red below]
This is not an issue with a many-to-one implementation as seen in the Person to Country relationship.
Am I doing something wrong here or is this a "unsupported feature"?
Notes: - We cannot use joined-subclass on our current system. - The below mapping, stack trace, etc is an exerpt of an app I wrote to reproduce the problem. I'll email the code thorugh on request.
NHibernate version:2.0.1.4000
Mapping documents: <class table="Person" name="JoinedSubclass.Person, JoinedSubclass" lazy="false" discriminator-value="P"> <id name="Id" column="PersonId" type="Int32" unsaved-value="0"> <generator class="identity" /> </id> <discriminator column="Discriminator" type="Char"/> <property name="FirstName"/> <property name="LastName"/> <many-to-one name="Country" column="CountryId" cascade="all" lazy="false" class="JoinedSubclass.Country, JoinedSubclass"/> <subclass name="JoinedSubclass.Employee, JoinedSubclass" lazy="true" discriminator-value="E"> <join table="Employee"> <key column="PersonId"/> <property name="Designation"/> <many-to-one name="Employer" column="EmployerId" cascade="all" lazy="false" class="JoinedSubclass.Employer, JoinedSubclass"/> </join> </subclass> </class>
<class table="Employer" name="JoinedSubclass.Employer, JoinedSubclass" lazy="false" > <id name="Id" column="EmployerId" type="Int32" unsaved-value="0"><generator class="identity" /></id> <set name="Employees" table="Employee" cascade="all" inverse="true" lazy="false"> <key column="EmployerId"/> <one-to-many class="JoinedSubclass.Employee, JoinedSubclass"/> </set> <property name="Name"/> </class> <class table="Country" name="JoinedSubclass.Country, JoinedSubclass" lazy="false" > <id name="Id" column="CountryId" type="Int32" unsaved-value="0"> <generator class="identity" /> </id> <property name="Name"/> </class>
Code between sessionFactory.openSession() and session.close(): currentSession.Load<Employer>(38);
Full stack trace of any exception that occurs: at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type) at NHibernate.Loader.Collection.CollectionLoader.Initialize(Object id, ISessionImplementor session) at NHibernate.Persister.Collection.AbstractCollectionPersister.Initialize(Object key, ISessionImplementor session) at NHibernate.Event.Default.DefaultInitializeCollectionEventListener.OnInitializeCollection(InitializeCollectionEvent event) at NHibernate.Impl.SessionImpl.InitializeCollection(IPersistentCollection collection, Boolean writing) at NHibernate.Collection.AbstractPersistentCollection.ForceInitialization() at NHibernate.Engine.StatefulPersistenceContext.InitializeNonLazyCollections() at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) at NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister) at NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId) at NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session) at NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType) at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType) at NHibernate.Impl.SessionImpl.Load(Type clazz, Object id) at JoinedSubclass.NHibernateHelper.SaveOrUpdate(IDomainClass inObject)
Name and version of the database you are using: SQL Server 2005
The generated SQL (show_sql=true): exec sp_executesql N'SELECT employees0_.EmployerId as EmployerId3_, employees0_.PersonId as PersonId3_, employees0_.PersonId as PersonId0_2_, employees0_.FirstName as FirstName0_2_, employees0_.LastName as LastName0_2_, employees0_.CountryId as CountryId0_2_, employees0_1_.Designation as Designat2_1_2_, employees0_1_.EmployerId as EmployerId1_2_, country1_.CountryId as CountryId3_0_, country1_.Name as Name3_0_, employer2_.EmployerId as EmployerId2_1_, employer2_.Name as Name2_1_ FROM Person employees0_ inner join Employee employees0_1_ on employees0_.PersonId=employees0_1_.PersonId left outer join Country country1_ on employees0_.CountryId=country1_.CountryId left outer join Employer employer2_ on employees0_1_.EmployerId=employer2_.EmployerId WHERE employees0_.EmployerId=@p0',N'@p0 int',@p0=37
|