public async Task SelectModeChildFetchForMultipleCollectionsAsync() { using (var session = OpenSession()) { EntityComplex root = null; root = await(session .QueryOver(() => root) .Where(r => r.Id == _parentEntityComplexId) .SingleOrDefaultAsync()); await(session .QueryOver(() => root) //Only ID is added to SELECT statement for root so it's index scan only .Fetch(SelectMode.ChildFetch, ec => ec) .Fetch(SelectMode.Fetch, ec => ec.ChildrenList) .Where(r => r.Id == _parentEntityComplexId) .ListAsync()); await(session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, ec => ec) .Fetch(SelectMode.Fetch, ec => ec.ChildrenListEmpty) .Where(r => r.Id == _parentEntityComplexId) .ListAsync()); Assert.That(root?.ChildrenList, Is.Not.Null); Assert.That(root?.ChildrenListEmpty, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList), "ChildrenList must be initialized"); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenListEmpty), "ChildrenListEmpty must be initialized"); Assert.That(root?.ChildrenList, Is.Not.Empty, "ChildrenList must not be empty"); Assert.That(root?.ChildrenListEmpty, Is.Empty, "ChildrenListEmpty must be empty"); } }
public void SelectModeDetachedQueryOver() { using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex root = null; root = QueryOver.Of(() => root) .Where(x => x.Id == _parentEntityComplexId) .Fetch(SelectMode.Fetch, r => r.Child1) .GetExecutableQueryOver(session) .SingleOrDefault(); Assert.That(root, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root), Is.True); Assert.That(root.Child1, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root.Child1), Is.True, "Joined ManyToOne Child1 should not be fetched."); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
public async Task SelectModeJoinOnlyAsync() { using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex root = null; root = await(session.QueryOver(() => root) //Child1 is required solely for filtering, no need to be fetched, so skip it from select statement .JoinQueryOver(r => r.Child1, JoinType.InnerJoin) .Fetch(SelectMode.JoinOnly, child1 => child1) .Take(1) .SingleOrDefaultAsync()); Assert.That(root, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root), Is.True); Assert.That(root.Child1, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root.Child1), Is.False, "Joined ManyToOne Child1 should not be fetched."); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
public void FetchWithAliasedJoinFuture() { using (var session = OpenSession()) { EntityComplex alias = null; EntitySimpleChild child1 = null; var list = session.QueryOver <EntityComplex>(() => alias) .Where(ec => ec.Id == _parentEntityComplexId) .JoinQueryOver(() => alias.Child1, () => child1) .Fetch(SelectMode.Fetch, () => alias.ChildrenList) .TransformUsing(Transformers.DistinctRootEntity) .Future() .GetEnumerable() .ToList(); var childList = list[0].ChildrenList; Assert.That(list[0].ChildrenList.Count, Is.GreaterThan(1)); Assert.That(list[0].ChildrenList, Is.EqualTo(list[0].ChildrenList.OrderByDescending(c => c.OrderIdx)), "wrong order"); } }
public async Task SelectModeChildFetchLoadsNotLoadedObjectAsync() { using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex root = null; root = await(session.QueryOver(() => root) .Fetch(SelectMode.ChildFetch, r => r) .JoinQueryOver(ec => ec.ChildrenList) .Fetch(SelectMode.Fetch, simpleChild => simpleChild) .Take(1) .SingleOrDefaultAsync()); Assert.That(root, Is.Not.Null, "root is not loaded"); Assert.That(NHibernateUtil.IsInitialized(root), Is.False, "root should not be initialized"); Assert.That(sqlLog.Appender.GetEvents(), Has.Length.EqualTo(1), "Only one SQL select is expected"); // The root was not initialized but its children collection is immediately initialized... A bit weird feature. Assert.That(NHibernateUtil.IsInitialized(root.ChildrenList), Is.True, "root children should be initialized"); Assert.That(root.ChildrenList, Has.Count.EqualTo(1).And.None.Null, "Unexpected children collection content"); } }
public void CacheableFetchWithAliasedJoinFuture() { using (var session = OpenSession()) { EntityComplex alias = null; EntitySimpleChild child1 = null; var list = session.QueryOver <EntityComplex>(() => alias) .Where(ec => ec.Id == _parentEntityComplexId) .JoinQueryOver(() => alias.Child1, () => child1) .Fetch(SelectMode.Fetch, () => alias.ChildrenList) .TransformUsing(Transformers.DistinctRootEntity) .Cacheable() .Future() .GetEnumerable() .ToList(); EntityComplex value = null; Assert.DoesNotThrow(() => value = list[0]); Assert.That(value, Is.Not.Null); } using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex alias = null; EntitySimpleChild child1 = null; var list = session.QueryOver <EntityComplex>(() => alias) .Where(ec => ec.Id == _parentEntityComplexId) .JoinQueryOver(() => alias.Child1, () => child1) .Fetch(SelectMode.Fetch, () => alias.ChildrenList) .TransformUsing(Transformers.DistinctRootEntity) .Cacheable() .Future() .ToList(); EntityComplex value = null; Assert.DoesNotThrow(() => value = list[0]); Assert.That(value, Is.Not.Null); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(0), "Query is expected to be retrieved from cache"); } }
public void SelectModeChildFetchDeep_SingleDbRoundtrip_Aliased() { SkipFutureTestIfNotSupported(); using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex root = null; var rootFuture = session .QueryOver(() => root) .Future(); session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, () => root) .Fetch(SelectMode.Fetch, () => root.ChildrenList) .Future(); session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, () => root, () => root.ChildrenList) .Fetch(SelectMode.Fetch, () => root.ChildrenList[0].Children) .Future(); session .QueryOver(() => root) .Fetch(SelectMode.JoinOnly, () => root.ChildrenList) .Fetch(SelectMode.ChildFetch, () => root, () => root.ChildrenList[0].Children) .Fetch(SelectMode.Fetch, () => root.ChildrenList[0].Children[0].Children) .Future(); root = rootFuture.ToList().First(r => r.Id == _parentEntityComplexId); Assert.That(root?.ChildrenList, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList)); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList[0].Children)); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList[0].Children[0].Children)); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
public async Task SelectModeJoinOnlyEntityJoinAsync() { using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex parentJoin = null; EntitySimpleChild rootChild = null; rootChild = await(session.QueryOver(() => rootChild) .JoinEntityQueryOver(() => parentJoin, Restrictions.Where(() => rootChild.ParentId == parentJoin.Id)) .Fetch(SelectMode.JoinOnly, a => a) .Take(1) .SingleOrDefaultAsync()); parentJoin = await(session.LoadAsync <EntityComplex>(rootChild.ParentId)); Assert.That(rootChild, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(rootChild), Is.True); Assert.That(rootChild.ParentId, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(parentJoin), Is.False, "Entity Join must not be initialized."); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
public async Task SelectModeChildFetchForMultipleCollections_SingleDbRoundtripAsync() { SkipFutureTestIfNotSupported(); using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex root = null; var futureRoot = session .QueryOver(() => root) .Where(r => r.Id == _parentEntityComplexId) .FutureValue(); session .QueryOver(() => root) //Only ID is added to SELECT statement for root so it's index scan only .Fetch(SelectMode.ChildFetch, ec => ec) .Fetch(SelectMode.Fetch, ec => ec.ChildrenList) .Where(r => r.Id == _parentEntityComplexId) .Future(); session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, ec => ec) .Fetch(SelectMode.Fetch, ec => ec.ChildrenListEmpty) .Where(r => r.Id == _parentEntityComplexId) .Future(); root = await(futureRoot.GetValueAsync()); Assert.That(root?.ChildrenList, Is.Not.Null); Assert.That(root?.ChildrenListEmpty, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList), "ChildrenList must be initialized"); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenListEmpty), "ChildrenListEmpty must be initialized"); Assert.That(root?.ChildrenList, Is.Not.Empty, "ChildrenList must not be empty"); Assert.That(root?.ChildrenListEmpty, Is.Empty, "ChildrenListEmpty must be empty"); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
public async Task SelectModeChildFetchDeep_AliasedAsync() { using (var session = OpenSession()) { EntityComplex root = null; var list = await(session .QueryOver(() => root) .ListAsync()); await(session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, () => root) .Fetch(SelectMode.Fetch, () => root.ChildrenList) .ListAsync()); await(session .QueryOver(() => root) .Fetch(SelectMode.ChildFetch, () => root, () => root.ChildrenList) .Fetch(SelectMode.Fetch, () => root.ChildrenList[0].Children) .ListAsync()); await(session .QueryOver(() => root) .Fetch(SelectMode.JoinOnly, () => root.ChildrenList) .Fetch(SelectMode.ChildFetch, () => root, () => root.ChildrenList[0].Children) .Fetch(SelectMode.Fetch, () => root.ChildrenList[0].Children[0].Children) .ListAsync()); root = list.First(r => r.Id == _parentEntityComplexId); Assert.That(root?.ChildrenList, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList)); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList[0].Children)); Assert.That(NHibernateUtil.IsInitialized(root?.ChildrenList[0].Children[0].Children)); } }
public async Task SelectModeFetchLazyPropertiesForEntityJoinAsync() { using (var sqlLog = new SqlLogSpy()) using (var session = OpenSession()) { EntityComplex parentJoin = null; EntitySimpleChild rootChild = null; rootChild = await(session.QueryOver(() => rootChild) .JoinEntityQueryOver(() => parentJoin, Restrictions.Where(() => rootChild.ParentId == parentJoin.Id)) .Fetch(SelectMode.FetchLazyProperties, ec => ec) .Take(1) .SingleOrDefaultAsync()); parentJoin = await(session.LoadAsync <EntityComplex>(rootChild.ParentId)); Assert.That(rootChild, Is.Not.Null); Assert.That(NHibernateUtil.IsInitialized(rootChild), Is.True); Assert.That(NHibernateUtil.IsInitialized(parentJoin), Is.True); Assert.That(NHibernateUtil.IsPropertyInitialized(parentJoin, nameof(parentJoin.LazyProp)), Is.Not.Null.Or.Empty); Assert.That(parentJoin.LazyProp, Is.Not.Null.Or.Empty); Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected"); } }
protected override void OnSetUp() { using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { var child1 = new EntitySimpleChild { Name = "Child1", LazyProp = "LazyFromSimpleChild1", Children = new List <Level2Child> { new Level2Child() { Name = "Level2.1", Children = new List <Level3Child> { new Level3Child { Name = "Level3.1.1", }, new Level3Child { Name = "Level3.1.2" }, } }, new Level2Child { Name = "Level2.2", Children = new List <Level3Child> { new Level3Child { Name = "Level3.2.1" }, new Level3Child { Name = "Level3.2.2" }, } } }, OrderIdx = 100 }; var child2 = new EntitySimpleChild { Name = "Child2", LazyProp = "LazyFromSimpleChild2", }; var child3 = new EntitySimpleChild { Name = "Child3", OrderIdx = 0 }; var child4 = new EntitySimpleChild { Name = "Child4", OrderIdx = 50 }; var parent = new EntityComplex { Name = "ComplexEntityParent", Child1 = child1, Child2 = child2, LazyProp = "SomeBigValue", SameTypeChild = new EntityComplex() { Name = "ComplexEntityChild" }, ChildrenList = new List <EntitySimpleChild> { child3, child1, child4 }, ChildrenListEmpty = new List <EntityComplex> { }, }; session.Save(new EntityEager() { Name = "Eager", ChildrenList = new List <EntityEagerChild> { new EntityEagerChild() { Name = "EagerChild" } } }); session.Save(child1); session.Save(child2); session.Save(parent.SameTypeChild); session.Save(parent); session.Flush(); transaction.Commit(); _parentEntityComplexId = parent.Id; } }