Skip to content

Commit cbea12e

Browse files
bahusoidfredericDelaporte
authored andcommitted
Fix criteria collection ordering (nhibernate#1997)
1 parent 7ccb678 commit cbea12e

File tree

4 files changed

+94
-31
lines changed

4 files changed

+94
-31
lines changed

src/NHibernate.Test/Async/Criteria/SelectModeTest/SelectModeTest.cs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,23 @@ public void SkipRootEntityIsNotSupportedAsync()
395395
}
396396
}
397397

398+
[Test]
399+
public async Task OrderedInnerJoinFetchAsync()
400+
{
401+
using (var session = OpenSession())
402+
{
403+
var list = await (session.QueryOver<EntityComplex>()
404+
.Where(ec => ec.Id == _parentEntityComplexId)
405+
.JoinQueryOver(c => c.ChildrenList).Fetch(SelectMode.Fetch, child => child)
406+
.TransformUsing(Transformers.DistinctRootEntity)
407+
.ListAsync());
408+
409+
var childList = list[0].ChildrenList;
410+
Assert.That(list[0].ChildrenList.Count, Is.GreaterThan(1));
411+
Assert.That(list[0].ChildrenList, Is.EqualTo(list[0].ChildrenList.OrderByDescending(c => c.OrderIdx)), "wrong order");
412+
}
413+
}
414+
398415
[Test, Obsolete]
399416
public async Task FetchModeEagerForLazyAsync()
400417
{
@@ -562,15 +579,19 @@ protected override HbmMapping GetMappings()
562579
m.Column("SameTypeChildId");
563580
m.ForeignKey("none");
564581
});
565-
MapList(rc, ep => ep.ChildrenList);
582+
MapList(rc, ep => ep.ChildrenList, mapper: m => m.OrderBy("OrderIdx desc"));
566583
MapList(rc, ep => ep.ChildrenListEmpty);
567584
});
568585

569586
MapSimpleChild(
570587
mapper,
571588
default(EntitySimpleChild),
572589
c => c.Children,
573-
rc => { rc.Property(sc => sc.LazyProp, mp => mp.Lazy(true)); });
590+
rc =>
591+
{
592+
rc.Property(sc => sc.LazyProp, mp => mp.Lazy(true));
593+
rc.Property(sc => sc.OrderIdx);
594+
});
574595
MapSimpleChild(mapper, default(Level2Child), c => c.Children);
575596
MapSimpleChild<Level3Child>(mapper);
576597

@@ -598,7 +619,7 @@ private static void MapSimpleChild<TChild, TSubChild>(ModelMapper mapper, TChild
598619
});
599620
}
600621

601-
private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Expression<Func<TParent, IEnumerable<TElement>>> expression, CollectionFetchMode fetchMode = null) where TParent : class
622+
private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Expression<Func<TParent, IEnumerable<TElement>>> expression, CollectionFetchMode fetchMode = null, Action<IBagPropertiesMapper<TParent, TElement>> mapper = null) where TParent : class
602623
{
603624
rc.Bag(
604625
expression,
@@ -620,6 +641,7 @@ private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Express
620641
{
621642
m.Fetch(fetchMode);
622643
}
644+
mapper?.Invoke(m);
623645
},
624646
a => a.OneToMany());
625647
}
@@ -682,7 +704,8 @@ protected override void OnSetUp()
682704
},
683705
}
684706
}
685-
}
707+
},
708+
OrderIdx = 100
686709
};
687710

688711
var child2 = new EntitySimpleChild
@@ -691,6 +714,17 @@ protected override void OnSetUp()
691714
LazyProp = "LazyFromSimpleChild2",
692715
};
693716

717+
var child3 = new EntitySimpleChild
718+
{
719+
Name = "Child3",
720+
OrderIdx = 0
721+
};
722+
var child4 = new EntitySimpleChild
723+
{
724+
Name = "Child4",
725+
OrderIdx = 50
726+
};
727+
694728
var parent = new EntityComplex
695729
{
696730
Name = "ComplexEntityParent",
@@ -701,7 +735,7 @@ protected override void OnSetUp()
701735
{
702736
Name = "ComplexEntityChild"
703737
},
704-
ChildrenList = new List<EntitySimpleChild> {child1},
738+
ChildrenList = new List<EntitySimpleChild> {child3, child1, child4 },
705739
ChildrenListEmpty = new List<EntityComplex> { },
706740
};
707741
session.Save(new EntityEager()

src/NHibernate.Test/Criteria/SelectModeTest/Entities.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public class EntitySimpleChild : BaseChild
4343
{
4444
public virtual IList<Level2Child> Children { get; set; } = new List<Level2Child>();
4545
public virtual string LazyProp { get; set; }
46+
public virtual int OrderIdx { get; set; }
4647
}
4748

4849
public class Level2Child : BaseChild

src/NHibernate.Test/Criteria/SelectModeTest/SelectModeTest.cs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,23 @@ public void SkipRootEntityIsNotSupported()
426426
}
427427
}
428428

429+
[Test]
430+
public void OrderedInnerJoinFetch()
431+
{
432+
using (var session = OpenSession())
433+
{
434+
var list = session.QueryOver<EntityComplex>()
435+
.Where(ec => ec.Id == _parentEntityComplexId)
436+
.JoinQueryOver(c => c.ChildrenList).Fetch(SelectMode.Fetch, child => child)
437+
.TransformUsing(Transformers.DistinctRootEntity)
438+
.List();
439+
440+
var childList = list[0].ChildrenList;
441+
Assert.That(list[0].ChildrenList.Count, Is.GreaterThan(1));
442+
Assert.That(list[0].ChildrenList, Is.EqualTo(list[0].ChildrenList.OrderByDescending(c => c.OrderIdx)), "wrong order");
443+
}
444+
}
445+
429446
[Test, Obsolete]
430447
public void FetchModeEagerForLazy()
431448
{
@@ -593,15 +610,19 @@ protected override HbmMapping GetMappings()
593610
m.Column("SameTypeChildId");
594611
m.ForeignKey("none");
595612
});
596-
MapList(rc, ep => ep.ChildrenList);
613+
MapList(rc, ep => ep.ChildrenList, mapper: m => m.OrderBy("OrderIdx desc"));
597614
MapList(rc, ep => ep.ChildrenListEmpty);
598615
});
599616

600617
MapSimpleChild(
601618
mapper,
602619
default(EntitySimpleChild),
603620
c => c.Children,
604-
rc => { rc.Property(sc => sc.LazyProp, mp => mp.Lazy(true)); });
621+
rc =>
622+
{
623+
rc.Property(sc => sc.LazyProp, mp => mp.Lazy(true));
624+
rc.Property(sc => sc.OrderIdx);
625+
});
605626
MapSimpleChild(mapper, default(Level2Child), c => c.Children);
606627
MapSimpleChild<Level3Child>(mapper);
607628

@@ -629,7 +650,7 @@ private static void MapSimpleChild<TChild, TSubChild>(ModelMapper mapper, TChild
629650
});
630651
}
631652

632-
private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Expression<Func<TParent, IEnumerable<TElement>>> expression, CollectionFetchMode fetchMode = null) where TParent : class
653+
private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Expression<Func<TParent, IEnumerable<TElement>>> expression, CollectionFetchMode fetchMode = null, Action<IBagPropertiesMapper<TParent, TElement>> mapper = null) where TParent : class
633654
{
634655
rc.Bag(
635656
expression,
@@ -651,6 +672,7 @@ private static void MapList<TParent, TElement>(IClassMapper<TParent> rc, Express
651672
{
652673
m.Fetch(fetchMode);
653674
}
675+
mapper?.Invoke(m);
654676
},
655677
a => a.OneToMany());
656678
}
@@ -713,7 +735,8 @@ protected override void OnSetUp()
713735
},
714736
}
715737
}
716-
}
738+
},
739+
OrderIdx = 100
717740
};
718741

719742
var child2 = new EntitySimpleChild
@@ -722,6 +745,17 @@ protected override void OnSetUp()
722745
LazyProp = "LazyFromSimpleChild2",
723746
};
724747

748+
var child3 = new EntitySimpleChild
749+
{
750+
Name = "Child3",
751+
OrderIdx = 0
752+
};
753+
var child4 = new EntitySimpleChild
754+
{
755+
Name = "Child4",
756+
OrderIdx = 50
757+
};
758+
725759
var parent = new EntityComplex
726760
{
727761
Name = "ComplexEntityParent",
@@ -732,7 +766,7 @@ protected override void OnSetUp()
732766
{
733767
Name = "ComplexEntityChild"
734768
},
735-
ChildrenList = new List<EntitySimpleChild> {child1},
769+
ChildrenList = new List<EntitySimpleChild> {child3, child1, child4 },
736770
ChildrenListEmpty = new List<EntityComplex> { },
737771
};
738772
session.Save(new EntityEager()

src/NHibernate/Loader/JoinWalker.cs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -882,32 +882,26 @@ protected SqlString OrderBy(IList<OuterJoinableAssociation> associations)
882882
OuterJoinableAssociation last = null;
883883
foreach (OuterJoinableAssociation oj in associations)
884884
{
885-
if (oj.JoinType == JoinType.LeftOuterJoin)
885+
if (oj.ShouldFetchCollectionPersister())
886886
{
887-
if (oj.Joinable.IsCollection)
887+
IQueryableCollection queryableCollection = (IQueryableCollection) oj.Joinable;
888+
if (queryableCollection.HasOrdering)
888889
{
889-
IQueryableCollection queryableCollection = (IQueryableCollection)oj.Joinable;
890-
if (queryableCollection.HasOrdering)
891-
{
892-
string orderByString = queryableCollection.GetSQLOrderByString(oj.RHSAlias);
893-
buf.Add(orderByString).Add(StringHelper.CommaSpace);
894-
}
890+
string orderByString = queryableCollection.GetSQLOrderByString(oj.RHSAlias);
891+
buf.Add(orderByString).Add(StringHelper.CommaSpace);
895892
}
896-
else
893+
}
894+
else if (!oj.IsCollection && last?.ShouldFetchCollectionPersister() == true)
895+
{
896+
// it might still need to apply a collection ordering based on a
897+
// many-to-many defined order-by...
898+
IQueryableCollection queryableCollection = (IQueryableCollection) last.Joinable;
899+
if (queryableCollection.IsManyToMany && last.IsManyToManyWith(oj))
897900
{
898-
// it might still need to apply a collection ordering based on a
899-
// many-to-many defined order-by...
900-
if (last != null && last.Joinable.IsCollection)
901+
if (queryableCollection.HasManyToManyOrdering)
901902
{
902-
IQueryableCollection queryableCollection = (IQueryableCollection)last.Joinable;
903-
if (queryableCollection.IsManyToMany && last.IsManyToManyWith(oj))
904-
{
905-
if (queryableCollection.HasManyToManyOrdering)
906-
{
907-
string orderByString = queryableCollection.GetManyToManyOrderByString(oj.RHSAlias);
908-
buf.Add(orderByString).Add(StringHelper.CommaSpace);
909-
}
910-
}
903+
string orderByString = queryableCollection.GetManyToManyOrderByString(oj.RHSAlias);
904+
buf.Add(orderByString).Add(StringHelper.CommaSpace);
911905
}
912906
}
913907
}

0 commit comments

Comments
 (0)