Skip to content

Commit 7fd1a9a

Browse files
maca88fredericDelaporte
authored andcommitted
Fix NRE when having subselect and nullable value selection for Linq query provider
1 parent 74b97af commit 7fd1a9a

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,39 @@ public async Task CanSelectConditionalEntityValueWithEntityComparisonAsync()
453453
Assert.That(fatherInsteadOfChild, Has.Exactly(2).EqualTo("5678"));
454454
}
455455

456+
[Test]
457+
public async Task CanExecuteMethodWithNullObjectAndSubselectAsync()
458+
{
459+
var list1 = await (db.Animals.Select(
460+
a => new
461+
{
462+
NullableId = (int?) a.Father.Father.Id,
463+
})
464+
.ToListAsync());
465+
Assert.That(list1, Has.Count.GreaterThan(0));
466+
Assert.That(list1[0].NullableId, Is.Null);
467+
468+
var list2 = await (db.Animals.Select(
469+
a => new
470+
{
471+
Descriptions = a.Children.Select(z => z.Description)
472+
})
473+
.ToListAsync());
474+
Assert.That(list2, Has.Count.GreaterThan(0));
475+
Assert.That(list2[0].Descriptions, Is.Not.Null);
476+
477+
var list3 = await (db.Animals.Select(
478+
a => new
479+
{
480+
NullableId = (int?) a.Father.Father.Id,
481+
Descriptions = a.Children.Select(z => z.Description)
482+
})
483+
.ToListAsync());
484+
Assert.That(list3, Has.Count.GreaterThan(0));
485+
Assert.That(list3[0].NullableId, Is.Null);
486+
Assert.That(list3[0].Descriptions, Is.Not.Null);
487+
}
488+
456489
[Test]
457490
public async Task CanSelectConditionalEntityValueWithEntityComparisonRepeatAsync()
458491
{

src/NHibernate.Test/Linq/SelectionTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,39 @@ public void CanSelectConditionalEntityValueWithEntityComparison()
492492
Assert.That(fatherInsteadOfChild, Has.Exactly(2).EqualTo("5678"));
493493
}
494494

495+
[Test]
496+
public void CanExecuteMethodWithNullObjectAndSubselect()
497+
{
498+
var list1 = db.Animals.Select(
499+
a => new
500+
{
501+
NullableId = (int?) a.Father.Father.Id,
502+
})
503+
.ToList();
504+
Assert.That(list1, Has.Count.GreaterThan(0));
505+
Assert.That(list1[0].NullableId, Is.Null);
506+
507+
var list2 = db.Animals.Select(
508+
a => new
509+
{
510+
Descriptions = a.Children.Select(z => z.Description)
511+
})
512+
.ToList();
513+
Assert.That(list2, Has.Count.GreaterThan(0));
514+
Assert.That(list2[0].Descriptions, Is.Not.Null);
515+
516+
var list3 = db.Animals.Select(
517+
a => new
518+
{
519+
NullableId = (int?) a.Father.Father.Id,
520+
Descriptions = a.Children.Select(z => z.Description)
521+
})
522+
.ToList();
523+
Assert.That(list3, Has.Count.GreaterThan(0));
524+
Assert.That(list3[0].NullableId, Is.Null);
525+
Assert.That(list3[0].Descriptions, Is.Not.Null);
526+
}
527+
495528
[Test]
496529
public void CanSelectConditionalEntityValueWithEntityComparisonRepeat()
497530
{

src/NHibernate/Linq/NestedSelects/SelectClauseRewriter.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ public override Expression Visit(Expression expression)
3838
return base.Visit(expression);
3939
}
4040

41+
protected override Expression VisitUnary(UnaryExpression node)
42+
{
43+
if (node.NodeType == ExpressionType.Convert &&
44+
(node.Operand is MemberExpression || node.Operand is QuerySourceReferenceExpression))
45+
{
46+
return AddAndConvertExpression(node.Operand, node.Type);
47+
}
48+
49+
return base.VisitUnary(node);
50+
}
51+
4152
protected override Expression VisitMember(MemberExpression expression)
4253
{
4354
return AddAndConvertExpression(expression);
@@ -49,14 +60,19 @@ protected override Expression VisitQuerySourceReference(QuerySourceReferenceExpr
4960
}
5061

5162
private Expression AddAndConvertExpression(Expression expression)
63+
{
64+
return AddAndConvertExpression(expression, expression.Type);
65+
}
66+
67+
private Expression AddAndConvertExpression(Expression expression, System.Type type)
5268
{
5369
expressions.Add(new ExpressionHolder { Expression = expression, Tuple = tuple });
5470

5571
return Expression.Convert(
5672
Expression.ArrayIndex(
5773
Expression.Property(parameter, Tuple.ItemsProperty),
5874
Expression.Constant(expressions.Count - 1)),
59-
expression.Type);
75+
type);
6076
}
6177
}
6278
}

0 commit comments

Comments
 (0)