/// <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));
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
        /// <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));
        }
Пример #6
0
        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));
        }
Пример #7
0
        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));
        }