-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix to #9551 - Expression of type 'System.Object' cannot be used for …
…parameter of type 'Microsoft.EntityFrameworkCore.Metadata.IEntityType' Problem was that we made some assumptions when compiling include, that do not hold true for complex queries involving group by and other operations that follow. Once we build _Include(...) expression and try to substitute a qsre with it, we have compensation logic in case of groupby - trying to apply the substitution on the ElementSelector of the groupby. This logic is located in QueryModelExtensions.GetOutputExpression. However, we assume that the outermost query model is the one that contains the groupby result operator. For the queries in the bug, this is not the case - GroupBy result operator is a subquery and therefore our old logic was not detecting it correctly, causing an error. Fix is to find a correct query model (based on the qsre used in the Include result operator) and only after the correct QM (which can be in a subquery) is obtained, perform the compensation logic in QueryModelExtensions.GetOutputExpression. Additional fix is needed when compiling collection navigation includes. We manually craft the QM that fetches child elements, and also assume that the outermost parent QM is the one that needs to be joined to. Similar approach is used here - find the "real" QM referenced in the include and build the collection-fetching QM based on that instead.
- Loading branch information
Showing
7 changed files
with
321 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
src/EFCore/Query/ExpressionVisitors/Internal/QueryModelFindingVisitor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using JetBrains.Annotations; | ||
using Microsoft.EntityFrameworkCore.Utilities; | ||
using Remotion.Linq; | ||
using Remotion.Linq.Clauses; | ||
|
||
namespace Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal | ||
{ | ||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public class QueryModelFindingVisitor : QueryModelVisitorBase | ||
{ | ||
private readonly IQuerySource _querySource; | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public QueryModelFindingVisitor([NotNull] IQuerySource querySource) | ||
{ | ||
Check.NotNull(querySource, nameof(querySource)); | ||
|
||
_querySource = querySource; | ||
} | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public virtual QueryModel QueryModel { get; private set; } | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public override void VisitQueryModel(QueryModel queryModel) | ||
{ | ||
queryModel.TransformExpressions(new TransformingQueryModelExpressionVisitor<QueryModelFindingVisitor>(this).Visit); | ||
|
||
base.VisitQueryModel(queryModel); | ||
} | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel) | ||
{ | ||
if (fromClause == _querySource) | ||
{ | ||
QueryModel = queryModel; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index) | ||
{ | ||
if (fromClause == _querySource) | ||
{ | ||
QueryModel = queryModel; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public override void VisitJoinClause(JoinClause joinClause, QueryModel queryModel, int index) | ||
{ | ||
if (joinClause == _querySource) | ||
{ | ||
QueryModel = queryModel; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public override void VisitGroupJoinClause(GroupJoinClause groupJoinClause, QueryModel queryModel, int index) | ||
{ | ||
if (groupJoinClause == _querySource) | ||
{ | ||
QueryModel = queryModel; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,4 +24,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) | |
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.