Skip to content

Commit c3380e3

Browse files
authored
Support AsQueryable() call in nested Select (#2557)
Fixes #2540
1 parent 44f3406 commit c3380e3

File tree

4 files changed

+47
-9
lines changed

4 files changed

+47
-9
lines changed

src/NHibernate.Test/Async/Linq/NestedSelectsTests.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,7 @@ public async Task CanSelectWithWhereSubQueryAsync()
413413
Assert.AreEqual(3, list.Count);
414414
}
415415

416-
[KnownBug("GH-2540")]
417-
[Test]
416+
[Test(Description = "GH-2540")]
418417
public async Task CanSelectWithAsQueryableAndWhereSubQueryAsync()
419418
{
420419
var query = from timesheet in db.Timesheets
@@ -429,8 +428,22 @@ public async Task CanSelectWithAsQueryableAndWhereSubQueryAsync()
429428
Assert.AreEqual(3, list.Count);
430429
}
431430

432-
[KnownBug("GH-2540")]
433-
[Test]
431+
[Test(Description = "GH-2540")]
432+
public async Task CanSelectWithAsQueryableAndWhereSubQueryToArrayAsync()
433+
{
434+
var query = from timesheet in db.Timesheets
435+
select new
436+
{
437+
timesheet.Id,
438+
Entries = timesheet.Entries.AsQueryable().Where(e => e.NumberOfHours >= 0).ToArray()
439+
};
440+
441+
var list = await (query.ToListAsync());
442+
443+
Assert.AreEqual(3, list.Count);
444+
}
445+
446+
[Test(Description = "GH-2540")]
434447
public async Task CanSelectWithAsQueryableAndWhereSubQueryWithExternalPredicateAsync()
435448
{
436449
Expression<Func<TimesheetEntry, bool>> predicate = e => e.NumberOfHours >= 0;

src/NHibernate.Test/Linq/NestedSelectsTests.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ public void CanSelectWithWhereSubQuery()
415415
Assert.AreEqual(3, list.Count);
416416
}
417417

418-
[KnownBug("GH-2540")]
419-
[Test]
418+
[Test(Description = "GH-2540")]
420419
public void CanSelectWithAsQueryableAndWhereSubQuery()
421420
{
422421
var query = from timesheet in db.Timesheets
@@ -431,8 +430,22 @@ public void CanSelectWithAsQueryableAndWhereSubQuery()
431430
Assert.AreEqual(3, list.Count);
432431
}
433432

434-
[KnownBug("GH-2540")]
435-
[Test]
433+
[Test(Description = "GH-2540")]
434+
public void CanSelectWithAsQueryableAndWhereSubQueryToArray()
435+
{
436+
var query = from timesheet in db.Timesheets
437+
select new
438+
{
439+
timesheet.Id,
440+
Entries = timesheet.Entries.AsQueryable().Where(e => e.NumberOfHours >= 0).ToArray()
441+
};
442+
443+
var list = query.ToList();
444+
445+
Assert.AreEqual(3, list.Count);
446+
}
447+
448+
[Test(Description = "GH-2540")]
436449
public void CanSelectWithAsQueryableAndWhereSubQueryWithExternalPredicate()
437450
{
438451
Expression<Func<TimesheetEntry, bool>> predicate = e => e.NumberOfHours >= 0;

src/NHibernate/Linq/NestedSelects/NestedSelectRewriter.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ private static Expression ProcessExpression(QueryModel queryModel, ISessionFacto
9797
private static Expression ProcessSubquery(ISessionFactory sessionFactory, ICollection<ExpressionHolder> elementExpression, QueryModel queryModel, Expression @group, QueryModel subQueryModel)
9898
{
9999
var resultTypeOverride = subQueryModel.ResultTypeOverride;
100-
if (resultTypeOverride != null && !resultTypeOverride.IsArray && !resultTypeOverride.IsEnumerableOfT())
100+
if (resultTypeOverride != null && !resultTypeOverride.IsArray && !IsEnumerableOfT(resultTypeOverride))
101101
return null;
102102

103+
SubQueryFromClauseFlattener.ReWrite(subQueryModel);
103104
var subQueryMainFromClause = subQueryModel.MainFromClause;
104105

105106
var restrictions = subQueryModel.BodyClauses
@@ -128,6 +129,15 @@ private static Expression ProcessSubquery(ISessionFactory sessionFactory, IColle
128129
return BuildSubCollectionQuery(sessionFactory, elementExpression, @group, source, selector, elementType, collectionType);
129130
}
130131

132+
private static bool IsEnumerableOfT(System.Type type)
133+
{
134+
if (!type.IsGenericType)
135+
return false;
136+
137+
var typeDef = type.GetGenericTypeDefinition();
138+
return typeDef == typeof(IEnumerable<>) || typeDef == typeof(IQueryable<>);
139+
}
140+
131141
private static Expression ProcessMemberExpression(ISessionFactory sessionFactory, ICollection<ExpressionHolder> elementExpression, QueryModel queryModel, Expression @group, Expression memberExpression)
132142
{
133143
var join = new NhJoinClause(new NameGenerator(queryModel).GetNewName(),

src/NHibernate/Util/TypeExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ namespace NHibernate.Util
66
{
77
public static class TypeExtensions
88
{
9+
//Since 5.4
10+
[Obsolete("This method has no more usages and will be removed in a future version.")]
911
public static bool IsEnumerableOfT(this System.Type type)
1012
{
1113
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>);

0 commit comments

Comments
 (0)