NHibernate Lazy load and proxy object

124 views
Skip to first unread message

RoyWagner

unread,
Mar 19, 2009, 1:02:47 PM3/19/09
to nhusers
This is the situation:

I have an abstract Profile class and 2 derived classes let’s call the
ProfileA and ProfileB.
Then mapping structure that I use is table per class hierarchy.

I also have a user class that have reference to a Profile:

Public class User
{
public virtual Profile Profile { get; set; }
}

I use lazy load for the Profile property.

The problem is that when try to cast the User.Profile to one of the
derived classes(PofileA or ProfileB) I get an error that I can’t cast
ProfileProxy16982… to ProfileA.
NHibernate create ProfileProxy object in order to support the lazy
load and that prevent me from casting the Profile object.

The only solution I have right now is to cancel the lazy load.

Stefan Steinegger

unread,
Mar 20, 2009, 10:00:54 AM3/20/09
to nhusers
Why can't you cast it because of the proxy? If the proxy would
actually be derived from ProfileA, you should be able to cast it to
ProfileA. Are you sure that you don't actually have a proxy of
Profile? Check your mapping, did you define the subclasses and
discriminators correctly? What is the type you are storing?

If you turn off lazy loading, you'll see if there is still a problem.

kello

unread,
Mar 20, 2009, 4:31:54 PM3/20/09
to nhusers
I have run into this problem when using single table inheritance and a
table column as discriminator. At first I thought it was strange but
then thinking about it further I realized that when lazy loading NH
does not touch the database before creating the proxy object. Now how
should NH know if it should create a ProfileA-proxy or a ProfileB-
proxy without checking the database for the discrimiator value?

The answer is it cannot so it creates a proxy for the base class and
you get a Profile-proxy which of course is not castable to the derived
classes ProfileA or ProfileB.

Think of it this way. By telling NH to lazy-load you are telling it
not to look in the database but create a proxy instead and look in the
database later on. If the information that determines what proxy-type
it should create is in the database how could it possibly create an
proxy object of the correct type? And once the proxy object is created
as a base-class how could it possibly make it change into an derived
type when it accesses the database? It could of course look in the
database to determine the type of proxy to create but that would
defeat the whole purpose of lazy-loading.

This is what I think causes these types of problems but I can be wrong
because I have not confirmed it. I solved my problem by disabling lazy-
loading. I am also thinking about rewriting the code to use
composition instead of inheritance which I think would be a better
solution but currently I find inheritance to be easier to understand.
I think something like the player-role pattern could be used but I
still haven't reached a good understanding of how to use that pattern
and map it with NH....

/Jonas

Germán Schuager

unread,
Mar 20, 2009, 5:35:47 PM3/20/09
to nhu...@googlegroups.com
I've worked out a similar situation using interfaces like this:

interface IProfileA

class ProfileA : IProfileA

interface IProfileB

class ProfileB : IProfileB

interface IProfileProxy : IProfileA, IProfileB


then specifying proxy="Namespace.IProfileProxy" in the base class mapping and working against the interfaces.

kello

unread,
Mar 20, 2009, 8:39:23 PM3/20/09
to nhusers
I don't see how an interface that derives from two other interfaces
would help in doing different things depending on the type? For
example

if (Profile is ProfileA) DoA(); else if(Profile is ProfileB) DoB();

Or when using the Visitor pattern.... Am I missing something?

/Jonas
> > The only solution I have right now is to cancel the lazy load.- Hide quoted text -
>
> - Show quoted text -

rashack

unread,
Mar 21, 2009, 7:17:07 AM3/21/09
to nhusers
See my reply on the same topic in a duplicate thread:
http://groups.google.com/group/nhusers/browse_thread/thread/780d2264163ab33f?hl=en

Cheers,
Jarda

Germán Schuager

unread,
Mar 21, 2009, 8:07:31 AM3/21/09
to nhu...@googlegroups.com
Specifying IProfileProxy you can cast any lazy-loaded Profile to either IProfileA or IProfileB and then work against the interface.
Is that what you were asking for?

domonkos

unread,
Apr 3, 2009, 10:03:28 AM4/3/09
to nhusers
In this case both (User.Profile is IProfileA) and (User.Profile is
IProfileB) always be true.
And he still can't decide whether the User.Profile is instance of
ProfileA or ProfileB, am I right?

Germán Schuager

unread,
Apr 4, 2009, 8:46:37 AM4/4/09
to nhu...@googlegroups.com
You are right.
IIRC, in my case I've used other information (from my model) to know which type to use.

Perhaps this method cannot be used in every scenario.
Reply all
Reply to author
Forward
0 new messages