Open
Description
I have found that sometimes fetching lazy properties doesn't work and property is still lazy. I've prepared a test code to reproduce this issue:
public class EntityA
{
public EntityA()
{
Items = new HashSet<EntityB>();
}
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<EntityB> Items { get; set; }
}
public class EntityB
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class EntityAMapping:ClassMapping<EntityA>
{
public EntityAMapping()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.Name, map =>
{
map.Length(256);
map.NotNullable(true);
});
Set(x => x.Items, v =>
{
v.Cascade(Cascade.None);
v.Key(x =>
{
x.Column("RiskId");
x.NotNullable(true);
});
v.Lazy(CollectionLazy.Extra);
v.Fetch(CollectionFetchMode.Subselect);
}, h => h.ManyToMany(m => m.Column("RiskAreaId")));
}
}
public class EntityBMapping:ClassMapping<EntityB>
{
public EntityBMapping()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.Name, map =>
{
map.Length(256);
map.NotNullable(true);
});
}
}
[TestFixture]
public class EmptyTest:NHibernateTestFixtureBase
{
[Test]
public void Test()
{
using (var session = _sessionFactory.OpenSession())
{
var entityB = new EntityB();
entityB.Name = "Name B";
session.Save(entityB);
var entityA = new EntityA();
entityA.Name = "Name A";
entityA.Items.Add(entityB);
session.Save(entityA);
session.Flush();
}
using (var session = _sessionFactory.OpenStatelessSession())
{
var obj=session.QueryOver<EntityA>().SingleOrDefault();
Assert.IsFalse(NHibernateUtil.IsInitialized(obj.Items));
obj=session.QueryOver<EntityA>().Fetch(SelectMode.Fetch,x=>x.Items).SingleOrDefault();
Assert.IsTrue(NHibernateUtil.IsInitialized(obj.Items));
obj=session.QueryOver<EntityA>().Fetch(SelectMode.Fetch,x=>x.Items)
.Select(Projections.RootEntity())
.SingleOrDefault();
Assert.IsTrue(NHibernateUtil.IsInitialized(obj.Items)); //exception. Items not fetched!
obj=session.QueryOver<EntityA>()
.Select(Projections.RootEntity().SetFetchLazyProperties())
.SingleOrDefault();
Assert.IsTrue(NHibernateUtil.IsInitialized(obj.Items)); //exception. Items not fetched!
obj=session.QueryOver<EntityA>().Fetch(SelectMode.Fetch,x=>x.Items)
.Select(Projections.RootEntity().SetFetchLazyProperties())
.SingleOrDefault();
Assert.IsTrue(NHibernateUtil.IsInitialized(obj.Items)); //exception. Items not fetched!
}
}
}
In this example if we have a QueryOver with a Select, then there is no way to eager fetch properties. Only way to force Items collection to be eager loaded is to change a mapping and set NoLazy instead of Extra.
If you need more info, please let me know