Skip to content

Commit

Permalink
Query: Check if parameter.Name is not null before comparing it with q…
Browse files Browse the repository at this point in the history
…uery parameter

Resolves #20485
- Parameters which are used inside lambda should get replaced with appropriate shaper/selector.
- All other parameters should be query parameters otherwise it is an error.

Resolves #18502
- Non query parameters should not get translated. Query parameters which are translated will always have value in QueryContext.
  • Loading branch information
smitpatel committed Apr 2, 2020
1 parent 2aaaa35 commit e88ea7d
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,15 @@ public override Expression Visit(Expression expression)
return parameterExpression;
}

return Expression.Call(
_getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type),
QueryCompilationContext.QueryContextParameter,
Expression.Constant(parameterExpression.Name));
if (parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true)
{
return Expression.Call(
_getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type),
QueryCompilationContext.QueryContextParameter,
Expression.Constant(parameterExpression.Name));
}

throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print()));

case MaterializeCollectionNavigationExpression _:
return base.Visit(expression);
Expand Down Expand Up @@ -163,9 +168,8 @@ private static readonly MethodInfo _getParameterValueMethodInfo
= typeof(CosmosProjectionBindingExpressionVisitor)
.GetTypeInfo().GetDeclaredMethod(nameof(GetParameterValue));

#pragma warning disable IDE0052 // Remove unread private members
[UsedImplicitly]
private static T GetParameterValue<T>(QueryContext queryContext, string parameterName)
#pragma warning restore IDE0052 // Remove unread private members
=> (T)queryContext.ParameterValues[parameterName];

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,9 @@ protected override Expression VisitNew(NewExpression newExpression)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override Expression VisitParameter(ParameterExpression parameterExpression)
=> new SqlParameterExpression(Check.NotNull(parameterExpression, nameof(parameterExpression)), null);
=> parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true
? new SqlParameterExpression(Check.NotNull(parameterExpression, nameof(parameterExpression)), null)
: null;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres
{
Check.NotNull(parameterExpression, nameof(parameterExpression));

if (parameterExpression.Name.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal))
if (parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true)
{
return Expression.Call(
_getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,15 @@ public override Expression Visit(Expression expression)
return expression;

case ParameterExpression parameterExpression:
return Expression.Call(
_getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type),
QueryCompilationContext.QueryContextParameter,
Expression.Constant(parameterExpression.Name));
if (parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true)
{
return Expression.Call(
_getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type),
QueryCompilationContext.QueryContextParameter,
Expression.Constant(parameterExpression.Name));
}

throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print()));

case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression:
return _selectExpression.AddCollectionProjection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,9 @@ protected override Expression VisitNew(NewExpression newExpression)
protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) => null;

protected override Expression VisitParameter(ParameterExpression parameterExpression)
=> new SqlParameterExpression(Check.NotNull(parameterExpression, nameof(parameterExpression)), null);
=> parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true
? new SqlParameterExpression(Check.NotNull(parameterExpression, nameof(parameterExpression)), null)
: null;

protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private static bool ClientSource(Expression expression)
|| expression is MemberInitExpression
|| expression is NewExpression
|| expression is ParameterExpression parameter
&& parameter.Name.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal);
&& parameter.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true;

private static bool CanConvertEnumerableToQueryable(Type enumerableType, Type queryableType)
{
Expand Down

0 comments on commit e88ea7d

Please sign in to comment.