Skip to content

QueryOver.Future/FutureValue does not load NoLazy children like QueryOver.SingleOrDefault()/List() #3565

Open
@VoNhatSinh

Description

@VoNhatSinh

Please see the attached file for a reproducible project (also includes database script, and unit test)
FutureDoesNotLoadNoLazyChildNHibernate.zip

Steps to reproduce:

In the context of my example project, I have a Post table and a Comment table. A Post has a one-to-many relationship with Comment. The PostMap is configured to use CollectionLazy.NoLazy for Comments.

I wrote four unit tests in the attached project to demonstrate an issue. I use Future/FutureValue to get Posts/Post, and I expected the related child Comments to be loaded and usable outside the session. However, it throws a LazyInitializationException.

I then tried another approach using QueryOver.List (which returns a list of entities) or QueryOver.SingleOrDefault, and in this case, I can use the Comments as expected.

Please see my comment below for the reason and discuss that. Thank you a lot.

public class TestLoadingNoLazy
    {
        private ISessionFactory _sessionFactory;

        [OneTimeSetUp]
        public void OneTimeSetUp()
        {
            var config = new Configuration();
            config = config.DataBaseIntegration(db =>
            {
                db.ConnectionString = @"Server=localhost;Database=NoLazyNHibernate;Integrated Security=true;";
                db.Dialect<MsSql2012Dialect>();
                db.Driver<Sql2008ClientDriver>();
            });

            var mapper = new ConventionModelMapper();
            mapper.AddMapping<PostMap>();
            mapper.AddMapping<CommentMap>();
            var hbmMappings = mapper.CompileMappingForAllExplicitlyAddedEntities();

            config.AddMapping(hbmMappings);
            _sessionFactory = config.BuildSessionFactory();
        }

        [OneTimeTearDown]
        public void OneTimeTearDown()
        {
            _sessionFactory.Close();
        }

        [Test]
        public void LoadListPosts__UsingFuture__ThrowLazyInitializationException()
        {
            // Arrange
            IList<Post> postFuture;
            using (var session = _sessionFactory.OpenSession())
            {
                postFuture = session.QueryOver<Post>()
                    .Where(x => x.Title == "Title")
                    .Future().ToList();
            }

            // Action
            Func<string> action = () => postFuture[0].Comments[0].Content;

            // Assert
            action.Should().ThrowExactly<LazyInitializationException>();
        }

        [Test]
        public void LoadListPosts__UsingList__LoadCommentsSuccessfully()
        {
            // Arrange
            IList<Post> postList;
            using (var session = _sessionFactory.OpenSession())
            {
                postList = session.QueryOver<Post>()
                    .Where(x => x.Title == "Title")
                    .List();
            }

            // Action
            Func<string> action = () => postList[0].Comments[0].Content;

            // Assert
            action.Should().NotThrow();
        }

        [Test]
        public void LoadOnePost__UsingFutureValue__ThrowLazyInitializationException()
        {
            // Arrange
            Post postFutureValue;
            using (var session = _sessionFactory.OpenSession())
            {
                postFutureValue = session.QueryOver<Post>()
                    .Where(x => x.Title == "Title")
                    .FutureValue().Value;
            }

            // Action
            Func<string> action = () => postFutureValue.Comments[0].Content;

            // Assert
            action.Should().ThrowExactly<LazyInitializationException>();
        }

        [Test]
        public void LoadOnePost__UsingSingleOrDefault__LoadCommentsSuccessfully()
        {
            // Arrange
            Post postFutureValue;
            using (var session = _sessionFactory.OpenSession())
            {
                postFutureValue = session.QueryOver<Post>()
                    .Where(x => x.Title == "Title")
                    .SingleOrDefault();
            }

            // Action
            Func<string> action = () => postFutureValue.Comments[0].Content;

            // Assert
            action.Should().NotThrow();
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions