In NHibernate, if an entity is lazy-loaded by one query, and then requested to be eager-loaded by a second query in the same session, the returned type in the second query is always a proxy (I believe a cached proxy from the first query). This can be demonstrated in this highly simplified and British example:
public class CarClassMap : ClassMap<Car>
{
public CarClassMap()
{
this.Id(x => x.Id);
this.Map(x => x.Model);
// note: lazy load by default
this.References(x => x.Colour).Column("ColourId").LazyLoad();
}
}
public class ColourClassMap : ClassMap<Colour>
{
public ColourClassMap()
{
this.Id(x => x.Id);
this.Map(x => x.Description);
}
}
public static void Main()
{
using (var session = CreateSessionFactory().OpenSession())
{
// note: both cars are the same colour in the database
var jaguar = session.QueryOver<Car>()
.Where(x => x.Id == 1)
.FutureValue()
.Value;
Console.WriteLine("Jaguar colour type=" + jaguar.Colour.GetType());
var aston =
session.QueryOver<Car>()
.Fetch(x => x.Colour).Eager //note: eager load
.Where(x => x.Id == 2)
.FutureValue()
.Value;
Console.WriteLine("Aston Martin colour type=" + aston.Colour.GetType());
}
Console.Read();
}
The output from this program is:
Jaguar colour type=ColourProxy
Aston Martin colour type=ColourProxy
Both 'Colour' properties are proxies, despite the second query requesting an eager load. However when running just the eager-load query:
public static void Main()
{
using (var session = CreateSessionFactory().OpenSession())
{
var aston =
session.QueryOver<Car>()
.Fetch(x => x.Colour).Eager
.Where(x => x.Id == 2)
.FutureValue()
.Value;
Console.WriteLine("Aston Martin colour type=" + aston.Colour.GetType());
}
Console.Read();
}
The output is:
Aston Martin colour type=TestApp.Colour
The concrete, underlying type.
In our real system, the returned object is passed to a mapping layer which performs some complex logic. This discrepancy is causing us issues because the property is typed differently depending on which queries have been previously issued in the Session.
Basically the question is how can we avoid a request for an eager-load resulting in a proxy, and rather force it to the concrete type? We know we can manually 'un-proxy' objects using NHibernate utilities but we would rather not have to do that every time this entity is queried. If possible we'd prefer a way to do it in the class map. Or is there an altogether better solution? Thanks.