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
Is There an Exponent Operator in C#
Wpf Binding - Default Value for Empty String
Detect Windows Font Size (100%, 125%, and 150%)
Lambda Expressions in Immediate Window for VS2015
Simulating Cross Context Joins--Linq/C#
Dynamically Changing Schema in Entity Framework Core
How to Check If Thread Finished Execution
Bug: Can't Choose Dates on a Datepicker That Fall Outside a Floating VSto Add-In
How to Make 'Always-On-Bottom'-Window
How to Intercept Console Output
Equivalent Code of Createobject in C#
C# Waiting for Multiple Threads to Finish
Adding Elements to an Xml File in C#
Create Object Instance of a Class Having Its Name in String Variable