Search code examples
nhibernatelazy-loadingnhibernate-mapping-by-code

I cannot turn off lazy loading in NHibernate


I'm aware that lazy-loading 'on' is the default setting in NHibernate. I switched lazy-loading off, using mapping-by-code, for the entity (Student) and the collection (Comments) contained within an entity. However a test including the use of SQL-Profiler shows that it does not load the collection from the database when the entity is accessed via a Session.Get(). I see only a 'Select' to get the entity (Student) from the Db. No 'Join' or 'Selects' to the collection table (Comments). Am I missing something? I'm using NH version 5.

Mapping:

using NHibernate.Mapping.ByCode.Conformist;
using NHibernate.Mapping.ByCode;

namespace Infrastructure.Repository.NH.Tests
{
    public class StudentSubclassMapping: JoinedSubclassMapping<Student>
    {
        public StudentSubclassMapping()
        {
            Lazy(false);
            Property(student => student.EnrollmentDate);

            List(student => student.Comments,
                listMapper =>
                { listMapper.Lazy(CollectionLazy.NoLazy);},
                relationMapper =>
                     relationMapper.Element());
        }
    }
}

Domain:

public class Student : Contact
{
    public virtual DateTime? EnrollmentDate { get; set; }
    public virtual IList<string> Comments { get; set; }
}

Test:

    public void Get_TestToCheckIfLazyLoadingIsTurnedOff()
    {
        using (var session = SessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var student = session.Get<Student>(2);
                transaction.Commit();
            }
        }
    }

Solution

  • Just tested this with NHibernate 5.0.3 and it seems to be working properly:

    NHibernate: SELECT student0_.student_key as id1_0_0_, student0_.EnrollmentDate as enrollmentdate2_1_0_ FROM Student student0_ inner join Contact student0_1_ on student0_.student_key=student0_1_.Id WHERE student0_.student_key=@p0;@p0 = 1 [Type: Int32 (0:0:0)]
    NHibernate: SELECT comments0_.student_key as student1_2_0_, comments0_.id as id2_2_0_, comments0_.idx as idx3_0_ FROM Comments comments0_ WHERE comments0_.student_key=@p0;@p0 = 1 [Type: Int32 (0:0:0)]
    

    The listMapper.Lazy(CollectionLazy.NoLazy) that you already have there should do the trick.

    I think that maybe you don't really have a Student with ID 2 in the database? If that's the case, you will only see NHibernate issuing the first query (over Contact/Student) and it will not issue a query over Comments as the Student does not exist.

    If you have a Student with ID 2 you should see the query to the Comments table right after the initial one.

    If you like, you can try adding listMapper.Fetch(CollectionFetchMode.Join) to bring both the Student and Comments in the same query, although I wouldn't generally recommend this.