Identifying Nhibernate Proxy Classes

Identifying NHibernate proxy classes

You can detect if a class is a NHibernate proxy by casting it to (unsurprisingly) INHibernateProxy.

If you need to get the underlying "real" object, use:

Session.GetSessionImplementation().PersistenceContext.Unproxy(proxiedObject)

You don't need to test for proxies to call Unproxy; it returns the original parameter if it's not a proxy.

Edit: I now use a different approach to get the underlying object, mostly to work around lazy loading and inheritance: http://sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html

Trying to deal with nHibernate proxy classes due to inheritance

The answer actually required using the Visitor pattern. NHibernate's return type is a proxy of the base class, so any attempts to cast to the desired type is not possible. The Visitor pattern allows you to identify the type of the object your after through polymorphism.

Nhibernate: Get real entity class instead of proxied class

You can unproxy class with this code

session.PersistenceContext.Unproxy(proxiedInstance)

Getting proxies of the correct type in NHibernate

It's easiest to turn off lazy loading for the animal class. You say it's mostly in memory anyway.

<class name="Animal" lazy="false">
<!-- ... -->
</class>

As a variant of that, you could also use no-proxy, see this post:

<property name="OwnedAnimal" lazy="no-proxy"/>

As far as I can see, it only works when the AnimalOwner actually is a proxy.

OR

You can use generics on the animal owner to make the reference a concrete class.

class AnimalOwner<TAnimal>
{
virtual TAnimal OwnedAnimal {get;set;}
}

class CatOwner : AnimalOwner<Cat>
{
}

class DogOwner : AnimalOwner<Dog>
{
}

OR

You can map the DogOwners and CatOwners in separate tables, and define the concrete animal type in the mapping.

<class name="CatOwner">
<!-- ... -->
<property name="OwnedAninal" class="Cat"/>
</class>
<class name="DogOwner">
<!-- ... -->
<property name="OwnedAninal" class="Dog"/>
</class>

OR

You mess a little around with NHibernate, as proposed in this blog. NH is actually able to return the real object behind the proxy. Here a bit simpler implementation as proposed there:

    public static T CastEntity<T>(this object entity) where T: class
{
var proxy = entity as INHibernateProxy;
if (proxy != null)
{
return proxy.HibernateLazyInitializer.GetImplementation() as T;
}
else
{
return entity as T;
}
}

which can be used like this:

Dog dog = dogOwner.OwnedAnimal.CastEntity<Dog>();

How do I compare an object with an NHibernate proxy object?

I believe you need to override GetHashCode and Equals in your entities.

NHibernate proxy class, what should I choose?

I've already used #1 & #2 and they behave equally apparently, no differences detected.

Extracted from nhforge.org blog:

We are
using LinFu without a special reason
even if I have the impression that
LinFu give us a very little
performance improvement. For who are
using NHibernate without an IoC
framework LinFu.DynamicProxy is more
than enough.

For who are working with
Castle.ActiveRecord and/or
Castle.Windsor, obviously, the best
choice is Castle.DynamicProxy2 (mean
NHibernate.ByteCode.Castle.ProxyFactoryFactory).

http://nhforge.org/blogs/nhibernate/archive/2008/11/09/nh2-1-0-bytecode-providers.aspx

Can you explain what does NHibernate 'proxy' basically mean?

It means that it will create a class that inherits your original entity, and override the actual property that would represent the associated class.

By that, it can implement logic that would fetch the data from DB in order to achieve the laziness, instead of always having that data available.

For Collections though, this is implemented in NHibernate versions of ISet and IList etc. This is only relevant in many-to-one or one-to-one relations.

Example:

public class YourEntity {
public virtual OtherEntity Entity { get; set; }
}

public class DynamicProxyEntity : YourEntity {
private OtherEntity entity;

public override OtherEntity Entity {
get { return entity = LoadFromDb(); }
set { this.entity = value; }
}
}

This is a very simplistic version of it, hopefully it will give you an insight on how it works. This of course can bring problems into your app because you won't have an instance of your actual Entity-type, but the derived one. If you've decorated your classes with attributes and such, those might not be identified (depending on your code). also, type checking etc can break if you're not careful.

Are there occasions when NHibernate won't return a proxy object?

Generally proxies are for lazy loading. Whenever you're fetching entitles by Get etc., you're not getting proxies, but the real objects. NHibernate don't use proxies when not necessary.

But if user has an Address, user.Address is INHibernateProxy will be true (unless lazy loading is turned off for this relationship).

For more info about how and when NHibernate handles proxies, see this article.

NHibernate proxy generation for internal setters vs private setters

This is a pure .NET language problem. Try it yourself:

public class A
{
public virtual string PrivateSetter { get; private set; }
public virtual string InternalSetter { get; internal set; }
}

in another assembly:

public class B : A
{
// works fine, private isn't derived at all
// you can omit the setter, make it public, internal to this
// assembly etc.
public override string PrivateSetter { get; set; }

// compilation time error: setter can't be overridden,
// there is no access to it.
public override string InternalSetter { get; internal set; }
}

By the way, I'm just analyzing an issue with private setters and proxies, so I'm not sure if the proxies really work in this case.

ObjectDataSource fails to bind list when NHibernate Proxy object if on the first position

This is the temp solution I came up with. It works, I just make sure that list which is binded to control has first object that is not proxy:

    public static IList<T> ToProxySafeList<T>(this IList<T> list)
where T: class
{
if (list.Count == 0) return list;

var proxy = list[0] as INHibernateProxy;
if (proxy != null)
{
list[0] = proxy.HibernateLazyInitializer.GetImplementation() as T;
}
return list;
}

Any suggestions?



Related Topics



Leave a reply



Submit