Hi,
I think I've run into a bug in 2.0.1, but I haven't found anything in
Jira and wanted to ask here before I posted a bug to make sure I'm not
just doing something stupid. I've got a class hierarchy with a table
per hierarchy mapping, and a class of type C that has 2 collections,
One of type IList<D> and one of type IList<E>. C, D, and E are all
derived from a type A and are all mapped as subclasses of A like in
the mapping below.
NHibernate doesn't seem to generate the right query for retrieving the
Ds and Es collections. I would expect those loads to have a WHERE
clause using the discriminator column and value, "WHERE
EntityType='D'", right? But it's not doing that. The query it
generates for loading the Ds collection (I can get this if I unmap the
Es collection), looks like this:
SELECT ds0_.ParentID as ParentID1_, ds0_.ID as ID1_, ds0_.ID as
ID0_0_, ds0_.ParentID as ParentID0_0_ FROM A ds0_ WHERE
ds0_.ParentID=@p0
And NHibernate loads the instance of type D as an object of type E,
which causes an exception (also pasted below). I can add a ...
where="EntityType='D'" attribute to the Ds bag mapping and then
everything loads correctly, but that doesn't seem right to me.
Am I doing something wrong or is this a real bug? Also, if it is a
real bug, can someone just point me in the direction of where to
look? I'd be happy to try my hand at fixing the issue and submitting
a patch but I'm just starting to debug through the NHibernate code.
Thanks. Also, here are the mappings, a class diagram, and then the
exception I am seeing:
-----------------------------------------------------------------------------------------------------
<hibernate-mapping default-lazy="false" namespace="NHTest"
assembly="NHTest" xmlns="urn:nhibernate-mapping-2.2">
<class name="A" abstract="true">
<id name="ID">
<generator class="guid.comb" />
</id>
<discriminator column="EntityType" length="64"/>
</class>
<subclass name="B" discriminator-value="B" extends="NHTest.A,
NHTest"/>
<subclass name="C" discriminator-value="C" extends="NHTest.A,
NHTest">
<many-to-one name="Parent" column="ParentID" class="NHTest.B,
NHTest"/>
<bag name="Ds" cascade="all-delete-orphan" inverse="true">
<key column="ParentID" foreign-key="FK_ParentID" />
<one-to-many class="NHTest.D, NHTest" />
</bag>
<bag name="Es" cascade="all-delete-orphan" inverse="true">
<key column="ParentID" foreign-key="FK_ParentID" />
<one-to-many class="NHTest.E, NHTest" />
</bag>
</subclass>
<subclass name="D" discriminator-value="D" extends="NHTest.A,
NHTest">
<many-to-one name="Parent" column="ParentID" class="NHTest.C,
NHTest"/>
</subclass>
<subclass name="E" discriminator-value="E" extends="NHTest.A,
NHTest">
<many-to-one name="Parent" column="ParentID" class="NHTest.C,
NHTest"/>
</subclass>
</hibernate-mapping>
-----------------------------------------------------------------------------------------------------
The class diagram for these classes looks like this:
-----------------------------------------------------------------------------------------------------
http://www.jonstelly.com/development/nhibernate-collection-issue/Model.png
-----------------------------------------------------------------------------------------------------
And the exception I get when trying to do a "FROM A" HQL query looks
like this:
-----------------------------------------------------------------------------------------------------
2008-11-19 17:17:20,562 [1] INFO NHibernate.Loader.Loader [(null)] -
select a0_.ID as ID0_, a0_.ParentID as ParentID0_, a0_.EntityType as
EntityType0_ from A a0_ NHibernate: select a0_.ID as ID0_,
a0_.ParentID as ParentID0_, a0_.EntityType as EntityType0_ from A a0_
2008-11-19 17:17:20,656 [1] INFO NHibernate.Loader.Loader [(null)] -
SELECT es0_.ParentID as ParentID1_, es0_.ID as ID1_, es0_.ID as
ID0_0_, es0_.ParentID as ParentID0_0_ FROM A es0_ WHERE
es0_.ParentID=@p0 NHibernate: SELECT es0_.ParentID as ParentID1_,
es0_.ID as ID1_, es0_.ID as ID0_0_, es0_.ParentID as ParentID0_0_ FROM
A es0_ WHERE es0_.ParentID=@p0; @p0 = 'c603975f-7e8c-44e1-
bdb2-9b59011ce9b5'
Unhandled Exception: NHibernate.WrongClassException: Object with id:
a024b45b-6a0b-4772-bef1-9b59011ce9c3 was not of the specified
subclass: NHTest.E (loading object was of wrong class [NHTest.D])
at NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs,
Int32 i, IEntityPersister persister, EntityKey key, Object obj,
LockMode lockMode, ISessionImplementor session)
at NHibernate.Loader.Loader.GetRow(IDataReader rs, ILoadable[]
persisters, EntityKey[] keys, Object optionalObject, EntityKey
optionalObjectKey, LockMode[] lockModes, IList hydratedObjects,
ISessionImplementor session)
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader
resultSet, ISessionImplementor session, QueryParameters
queryParameters, LockMode[] lockModeArray, EntityKey
optionalObjectKey, IList hydratedObjects, EntityKey[] keys,
BooleanreturnProxies)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session,
QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections
(ISessionImplementor session, QueryParameters queryParameters, Boolean
returnProxies)
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.DoList(ISessionImplementor session,
QueryParameters queryParameters)
at NHibernate.Loader.Loader.ListIgnoreQueryCache
(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Loader.List(ISessionImplementor session,
QueryParameters queryParameters, ISet`1 querySpaces, IType[]
resultTypes)
at NHibernate.Hql.Classic.QueryTranslator.List(ISessionImplementor
session, QueryParameters queryParameters)
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters
queryParameters, ISessionImplementor session, IList results)
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters
queryParameters, IList results)
at NHibernate.Impl.SessionImpl.List[T](String query,
QueryParameters parameters)
at NHibernate.Impl.QueryImpl.List[T]()
at NHTest.Program.Main(String[] args) in C:\Projects\NHTest\NHTest
\Program.cs:line 45