/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { return(TryBindMember(source, MemberIdentity.Create(propertyName), out var result) ? result : null); } if (TranslationFailed(methodCallExpression.Object, Visit(methodCallExpression.Object), out var sqlObject)) { return(null); } var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = methodCallExpression.Arguments[i]; if (TranslationFailed(argument, Visit(argument), out var sqlArgument)) { return(null); } arguments[i] = sqlArgument; } return(_methodCallTranslatorProvider.Translate(_model, sqlObject, methodCallExpression.Method, arguments)); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.IsEFPropertyMethod()) { if (Visit(methodCallExpression.Arguments[0]) is EntityShaperExpression entityShaper) { var entityType = entityShaper.EntityType; var property = entityType.FindProperty((string)((ConstantExpression)methodCallExpression.Arguments[1]).Value); return(_selectExpression.BindProperty(entityShaper.ValueBufferExpression, property)); } else { throw new InvalidOperationException(); } } var @object = (SqlExpression)Visit(methodCallExpression.Object); var failed = TranslationFailed(methodCallExpression.Object, @object); var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = (SqlExpression)Visit(methodCallExpression.Arguments[i]); failed |= (methodCallExpression.Arguments[i] != null && arguments[i] == null); } return(failed ? null : _methodCallTranslatorProvider.Translate(_model, @object, methodCallExpression.Method, arguments)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { return(TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out var result) ? result : null); } var @object = Visit(methodCallExpression.Object); if (TranslationFailed(methodCallExpression.Object, @object)) { return(null); } var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { return(null); } arguments[i] = (SqlExpression)argument; } return(_methodCallTranslatorProvider.Translate(_model, (SqlExpression)@object, methodCallExpression.Method, arguments)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { if (!TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out var result)) { throw new InvalidOperationException($"Property {propertyName} not found on {source}"); } return(result); } //if (methodCallExpression.Method.DeclaringType == typeof(Queryable)) //{ // var translation = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); // var subquery = (SelectExpression)translation.QueryExpression; // subquery.ApplyProjection(); // if (methodCallExpression.Method.Name == nameof(Queryable.Any) // || methodCallExpression.Method.Name == nameof(Queryable.All) // || methodCallExpression.Method.Name == nameof(Queryable.Contains)) // { // if (subquery.Tables.Count == 0 // && subquery.Projection.Count == 1) // { // return subquery.Projection[0].Expression; // } // throw new InvalidOperationException(); // } // return new SubSelectExpression(subquery); //} var @object = Visit(methodCallExpression.Object); if (TranslationFailed(methodCallExpression.Object, @object)) { return(null); } var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { return(null); } arguments[i] = (SqlExpression)argument; } return(_methodCallTranslatorProvider.Translate(_model, (SqlExpression)@object, methodCallExpression.Method, arguments)); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { return(BindProperty(source, propertyName)); } var subqueryTranslation = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subqueryTranslation != null) { if (subqueryTranslation.ResultType == ResultType.Enumerable) { return(null); } var subquery = (SelectExpression)subqueryTranslation.QueryExpression; subquery.ApplyProjection(); if (subquery.Projection.Count != 1) { return(null); } if ((methodCallExpression.Method.Name == nameof(Queryable.Any) || methodCallExpression.Method.Name == nameof(Queryable.All) || methodCallExpression.Method.Name == nameof(Queryable.Contains)) && subquery.Tables.Count == 0) { return(subquery.Projection[0].Expression); } return(new SubSelectExpression(subquery)); } var @object = Visit(methodCallExpression.Object); if (TranslationFailed(methodCallExpression.Object, @object)) { return(null); } var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { return(null); } arguments[i] = (SqlExpression)argument; } return(_methodCallTranslatorProvider.Translate(_model, (SqlExpression)@object, methodCallExpression.Method, arguments)); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { Type convertedType = null; if (source is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert) { source = unaryExpression.Operand; if (unaryExpression.Type != typeof(object)) { convertedType = unaryExpression.Type; } } if (source is EntityShaperExpression entityShaper) { var entityType = entityShaper.EntityType; if (convertedType != null) { entityType = entityType.RootType().GetDerivedTypesInclusive() .FirstOrDefault(et => et.ClrType == convertedType); } if (entityType != null) { var property = entityType.FindProperty(propertyName); return(BindProperty(entityShaper, property)); } } throw new InvalidOperationException(); } if (methodCallExpression.Method.DeclaringType == typeof(Queryable)) { var translation = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); var subquery = (SelectExpression)translation.QueryExpression; subquery.ApplyProjection(); if (methodCallExpression.Method.Name == nameof(Queryable.Any) || methodCallExpression.Method.Name == nameof(Queryable.All) || methodCallExpression.Method.Name == nameof(Queryable.Contains)) { if (subquery.Tables.Count == 0 && subquery.Projection.Count == 1) { return(subquery.Projection[0].Expression); } else { throw new InvalidOperationException(); } } else { return(new SubSelectExpression(subquery)); } } var @object = Visit(methodCallExpression.Object); if (TranslationFailed(methodCallExpression.Object, @object)) { return(null); } var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { return(null); } arguments[i] = (SqlExpression)argument; } return(_methodCallTranslatorProvider.Translate(_model, (SqlExpression)@object, methodCallExpression.Method, arguments)); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.IsEFPropertyMethod()) { var firstArgument = methodCallExpression.Arguments[0]; // In certain cases EF.Property would have convert node around the source. if (firstArgument is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert && unaryExpression.Type == typeof(object)) { firstArgument = unaryExpression.Operand; } if (firstArgument is EntityShaperExpression entityShaper) { return(BindProperty(entityShaper, (string)((ConstantExpression)methodCallExpression.Arguments[1]).Value)); } else { throw new InvalidOperationException(); } } if (methodCallExpression.Method.DeclaringType == typeof(Queryable)) { var translation = _queryableMethodTranslatingExpressionVisitorFactory.Create(_model).Visit(methodCallExpression); if (translation is ShapedQueryExpression shapedQuery) { var subquery = (SelectExpression)shapedQuery.QueryExpression; subquery.ApplyProjection(); if (methodCallExpression.Method.Name == nameof(Queryable.Any) || methodCallExpression.Method.Name == nameof(Queryable.All) || methodCallExpression.Method.Name == nameof(Queryable.Contains)) { if (subquery.Tables.Count == 0 && subquery.Projection.Count == 1) { return(subquery.Projection[0].Expression); } else { throw new InvalidOperationException(); } } else { return(new SubSelectExpression(subquery)); } } else { throw new InvalidOperationException(); } } var @object = (SqlExpression)Visit(methodCallExpression.Object); var failed = TranslationFailed(methodCallExpression.Object, @object); var arguments = new SqlExpression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = (SqlExpression)Visit(methodCallExpression.Arguments[i]); failed |= (methodCallExpression.Arguments[i] != null && arguments[i] == null); } return(failed ? null : _methodCallTranslatorProvider.Translate(_model, @object, methodCallExpression.Method, arguments)); }