Skip to content

Commit

Permalink
Fix to #3811 - .OrderBy on column 2 or more navigation properties awa…
Browse files Browse the repository at this point in the history
…y + .Include throws exception

Problem was that in IncludeExpressionVisitor -> VisitMethodCall, when building entity accessor from a MemberExpression, we incorrectly assumed that member expression will always be one level.

Fix is to add a method that will go down the Expression chain to find root of the given MemberExpression.
CR: Andrew
  • Loading branch information
maumar committed Nov 24, 2015
1 parent 0466934 commit 8c1e269
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,17 @@ public static Expression RemoveConvert([CanBeNull] this Expression expression)

return expression;
}

public static TExpression GetRootExpression<TExpression>([NotNull] this Expression expression)
where TExpression : Expression
{
MemberExpression memberExpression;
while ((memberExpression = expression as MemberExpression) != null)
{
expression = memberExpression.Expression;
}

return expression as TExpression;
}
}
}
10 changes: 1 addition & 9 deletions src/EntityFramework.Core/Query/EntityQueryModelVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,16 +1160,8 @@ public virtual TResult BindMethodCallExpression<TResult>(

if (ReferenceEquals(methodInfo, PropertyMethodInfo))
{
var targetExpression = methodCallExpression.Arguments[0];

MemberExpression memberExpression;
while ((memberExpression = targetExpression as MemberExpression) != null)
{
targetExpression = memberExpression.Expression;
}

var querySourceReferenceExpression
= targetExpression as QuerySourceReferenceExpression;
= methodCallExpression.Arguments[0].GetRootExpression<QuerySourceReferenceExpression>();

if (querySourceReferenceExpression == null
|| querySource == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ var entityAccessor
: Expression
.Lambda(
memberExpression,
(ParameterExpression)memberExpression.Expression);
memberExpression.GetRootExpression<ParameterExpression>());

return
Expression.Call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,29 @@ public virtual void Include_with_join_and_inheritance3()
}
}

[Fact]
public virtual void Include_with_nested_navigation_in_order_by()
{
using (var context = CreateContext())
{
var query = context.Weapons
.Include(w => w.Owner)
.OrderBy(e => e.Owner.CityOfBirth.Name);

var result = query.ToList();
Assert.Equal(9, result.Count);
Assert.Equal("Ephyra", result[0].Owner.CityOrBirthName);
Assert.Equal("Ephyra", result[1].Owner.CityOrBirthName);
Assert.Equal("Hanover", result[2].Owner.CityOrBirthName);
Assert.Equal("Hanover", result[3].Owner.CityOrBirthName);
Assert.Equal("Jacinto", result[4].Owner.CityOrBirthName);
Assert.Equal("Jacinto", result[5].Owner.CityOrBirthName);
Assert.Equal("Unknown", result[6].Owner.CityOrBirthName);
Assert.Equal("Unknown", result[7].Owner.CityOrBirthName);
Assert.Equal("Unknown", result[8].Owner.CityOrBirthName);
}
}

[Fact]
public virtual void Where_enum()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,24 @@ public override void Include_with_join_and_inheritance3()
Sql);
}

public override void Include_with_nested_navigation_in_order_by()
{
base.Include_with_nested_navigation_in_order_by();

Assert.Equal(
@"SELECT [w].[Id], [w].[AmmunitionType], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank]
FROM [Weapon] AS [w]
INNER JOIN [Gear] AS [w.Owner] ON [w].[OwnerFullName] = [w.Owner].[FullName]
INNER JOIN [City] AS [w.Owner.CityOfBirth] ON [w.Owner].[CityOrBirthName] = [w.Owner.CityOfBirth].[Name]
LEFT JOIN (
SELECT [g].*
FROM [Gear] AS [g]
WHERE ([g].[Discriminator] = 'Officer') OR ([g].[Discriminator] = 'Gear')
) AS [g] ON [w].[OwnerFullName] = [g].[FullName]
ORDER BY [w.Owner.CityOfBirth].[Name]",
Sql);
}

public override void Where_enum()
{
base.Where_enum();
Expand Down

0 comments on commit 8c1e269

Please sign in to comment.