<any> relationship to joined subclass? Must specify meta-types for subclasses?

8 views
Skip to first unread message

Jon Stelly

unread,
Nov 12, 2008, 10:22:24 AM11/12/08
to nhusers
Hi,

I've run into a problem, it might just be that I'm not understanding
something. A quick rundown of my domain model. I've got an Entity
class that is not mapped, and several derived classes that are
mapped. I have a class with a "TargetEntity" property that can refer
to any type of Entity. So I need an <any> mapping here, right? I
created the following mapping, but it looks like

<any name="TargetEntity" meta-type="System.String" id-
type="System.Guid">
<meta-value class="Eg.SomeEntity, Eg" value="SomeEntity"/>
<meta-value class="Eg.Person, Eg" value="Person"/>
<column name="TargetEntityType"/>
<column name="TargetEntityID"/>
</any>

So I have a class Person that derives from Entity. If I save a record
with a Target Person, everything is fine. But I have a class, User,
that is derived from Person and mapped as a joined-subclass to
Person. I sort of assumed that if I specified a meta-value for the
<class> at the root of any mapped class hierarchy, NHibernate would be
able to save any type in that hierarchy, sort of fitting with the way
polymorphic queries work for non-mapped classes, but it doesn't appear
that's the case. Does this mean I'd need to specify a <meta-value>
for any possible derived type that could end up in TargetEntity? This
would be over 200 different values, and I'd need to constantly keep
this <any> relationship updated with new releases.

Any thoughts? If the above is all correct, I need to come up with
another solution since the maintainability of the above would be
unworkable. If I have to come up with a different solution, does
anyone have any suggestions? I need the full entity there in the
Target property, so I can't just change that to a TargetID Guid
property.

Thanks in advance.

Ayende Rahien

unread,
Nov 12, 2008, 10:39:56 AM11/12/08
to nhu...@googlegroups.com
I would say that if you have 200 joins in the database, you have a different problem.

That said, at least on the face of it, it should be a polymorphic association.

Fabio Maulo

unread,
Nov 12, 2008, 10:52:19 AM11/12/08
to nhu...@googlegroups.com
2008/11/12 Jon Stelly <jons...@gmail.com>

 Does this mean I'd need to specify a <meta-value>
for any possible derived type that could end up in TargetEntity?  This
would be over 200 different values, and I'd need to constantly keep
this <any> relationship updated with new releases.

Not that mean that you want specify the meta-value.
Remove the <meta-type> and <meta-value> from the mapping.
Define :  <column name="TargetEntityType" length="500"/>
And take a look about what happen ;)
 
I don't know your use case but in NH2.1 (trunk) you can use generics and avoid <any>.

and the same but changing the mapping

--
Fabio Maulo

Jon Stelly

unread,
Nov 12, 2008, 1:57:50 PM11/12/08
to nhusers
interesting, maybe I misread the <any> documentation, but it made it
sound like you had to specify a <meta-value>.

I forgot to mention, I'm using the latest 2.0 build. It looks like
the TargetEntityType column gets set to the name of the class (just
the name, no namespace or assembly information) but then when I try to
load from the table, I get the following exception. Any ideas? Also,
thanks for the quick help so far.

NHibernate.MappingException: No persister for: Site
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String
entityName, Boolean throwIfNotFound) in Impl
\SessionFactoryImpl.cs:line 766
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String
entityName) in Impl\SessionFactoryImpl.cs:line 752
at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad
(LoadEvent event, LoadType loadType) in Event\Default
\DefaultLoadEventListener.cs:line 37
at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType
loadType) in Impl\SessionImpl.cs:line 2055
at NHibernate.Impl.SessionImpl.InternalLoad(String entityName,
Object id, Boolean eager, Boolean isNullable) in Impl
\SessionImpl.cs:line 1068
at NHibernate.Type.AnyType.ResolveAny(String entityName, Object id,
ISessionImplementor session) in Type\AnyType.cs:line 396
at NHibernate.Type.AnyType.ResolveIdentifier(Object value,
ISessionImplementor session, Object owner) in Type\AnyType.cs:line 107
at NHibernate.Engine.TwoPhaseLoad.InitializeEntity(Object entity,
Boolean readOnly, ISessionImplementor session, PreLoadEvent
preLoadEvent, PostLoadEvent postLoadEvent) in Engine
\TwoPhaseLoad.cs:line 69
at NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList
hydratedObjects, Object resultSetId, ISessionImplementor session,
Boolean readOnly) in Loader\Loader.cs:line 617
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session,
QueryParameters queryParameters, Boolean returnProxies) in Loader
\Loader.cs:line 466
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections
(ISessionImplementor session, QueryParameters queryParameters, Boolean
returnProxies) in Loader\Loader.cs:line 187
at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor
session, Object id, IType type) in Loader\Loader.cs:line 1603
at NHibernate.Loader.Collection.CollectionLoader.Initialize(Object
id, ISessionImplementor session) in Loader\Collection
\CollectionLoader.cs:line 30
at
NHibernate.Persister.Collection.AbstractCollectionPersister.Initialize
(Object key, ISessionImplementor session) in Persister\Collection
\AbstractCollectionPersister.cs:line 527
at
NHibernate.Event.Default.DefaultInitializeCollectionEventListener.OnInitializeCollection
(InitializeCollectionEvent event) in Event\Default
\DefaultInitializeCollectionEventListener.cs:line 42
at NHibernate.Impl.SessionImpl.InitializeCollection
(IPersistentCollection collection, Boolean writing) in Impl
\SessionImpl.cs:line 1342
at
NHibernate.Collection.AbstractPersistentCollection.ForceInitialization
() in Collection\AbstractPersistentCollection.cs:line 462
at
NHibernate.Engine.StatefulPersistenceContext.InitializeNonLazyCollections
() in Engine\StatefulPersistenceContext.cs:line 901
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections
(ISessionImplementor session, QueryParameters queryParameters, Boolean
returnProxies) in Loader\Loader.cs:line 193
at NHibernate.Loader.Loader.DoList(ISessionImplementor session,
QueryParameters queryParameters) in Loader\Loader.cs:line 1808
at NHibernate.Loader.Loader.ListIgnoreQueryCache
(ISessionImplementor session, QueryParameters queryParameters) in
Loader\Loader.cs:line 1718
at NHibernate.Loader.Loader.List(ISessionImplementor session,
QueryParameters queryParameters, ISet`1 querySpaces, IType[]
resultTypes) in Loader\Loader.cs:line 1712
at NHibernate.Hql.Classic.QueryTranslator.List(ISessionImplementor
session, QueryParameters queryParameters) in Hql\Classic
\QueryTranslator.cs:line 1286
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters
queryParameters, ISessionImplementor session, IList results) in Engine
\Query\HQLQueryPlan.cs:line 226
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters
queryParameters, IList results) in Impl\SessionImpl.cs:line 520
at NHibernate.Impl.SessionImpl.List[T](String query,
QueryParameters parameters) in Impl\SessionImpl.cs:line 499
at NHibernate.Impl.QueryImpl.List[T]() in Impl\QueryImpl.cs:line 95


On Nov 12, 9:52 am, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> 2008/11/12 Jon Stelly <jonste...@gmail.com>
>
> >  Does this mean I'd need to specify a <meta-value>
> > for any possible derived type that could end up in TargetEntity?  This
> > would be over 200 different values, and I'd need to constantly keep
> > this <any> relationship updated with new releases.
>
> Not that mean that you want specify the meta-value.
> Remove the <meta-type> and <meta-value> from the mapping.
> Define :  <column name="TargetEntityType" length="500"/>
> And take a look about what happen ;)
>
> I don't know your use case but in NH2.1 (trunk) you can use generics and
> avoid <any>.http://fabiomaulo.blogspot.com/2008/10/entity-name-in-action-strongly...

Jon Stelly

unread,
Nov 12, 2008, 2:13:01 PM11/12/08
to nhusers
Sorry, my previous message wasn't clear. I made the changes that
Fabio suggested, and now I can save correctly, but when loading from
that table, I get the exception I just posted.

Fabio Maulo

unread,
Nov 12, 2008, 2:59:47 PM11/12/08
to nhu...@googlegroups.com
2008/11/12 Jon Stelly <jons...@gmail.com>

Sorry, my previous message wasn't clear.  I made the changes that
Fabio suggested, and now I can save correctly, but when loading from
that table, I get the exception I just posted.

The name saved in NH2.0.x should be the EntityName (class.FullName)...
Sometimes I need a test for it because <any> is not so used.
--
Fabio Maulo

Jon Stelly

unread,
Nov 13, 2008, 2:51:56 AM11/13/08
to nhusers
Wanted to say that your suggestion works, Fabio. The issue I was
seeing with that last exception was a build issue on my end, once I
got that squared away, everything is working fine.

Thanks for the help.


On Nov 12, 1:59 pm, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> 2008/11/12 Jon Stelly <jonste...@gmail.com>
>

Fabio Maulo

unread,
Nov 13, 2008, 7:09:03 AM11/13/08
to nhu...@googlegroups.com
Thank to you for the reply. Now I can work in something else instead write another test.

2008/11/13 Jon Stelly <jons...@gmail.com>



--
Fabio Maulo
Reply all
Reply to author
Forward
0 new messages