Skip to content

QueryOver with Select and Fetch not working correctly #2698

Open
@mm-development

Description

@mm-development

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions