private bool IsGroupByAggregateSubQuery(QueryModel queryModel)
        {
            if (queryModel.MainFromClause.FromExpression.Type.IsGrouping() &&
                queryModel.BodyClauses.Count == 0 &&
                queryModel.ResultOperators.Count == 1 &&
                _aggregateResultOperators.Contains(queryModel.ResultOperators[0].GetType()) &&
                _queryModelStack.Count > 0 &&
                !_queryModelStack.Peek().BodyClauses.OfType <IQuerySource>().Any())
            {
                var groupResultOperator
                    = (GroupResultOperator)
                      ((SubQueryExpression)
                       ((FromClauseBase)queryModel.MainFromClause.FromExpression.TryGetReferencedQuerySource())
                       .FromExpression)
                      .QueryModel.ResultOperators.Last();

                MemberAccessBindingExpressionVisitor.GetPropertyPath(
                    queryModel.SelectClause.Selector, _queryModelVisitor.QueryCompilationContext, out var qsre);

                if (qsre != null ||
                    queryModel.SelectClause.Selector.RemoveConvert() is ConstantExpression ||
                    groupResultOperator.ElementSelector.NodeType == ExpressionType.New ||
                    groupResultOperator.ElementSelector.NodeType == ExpressionType.MemberInit)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 2
0
        private Expression RewriteNullEquality(ExpressionType nodeType, Expression nonNullExpression)
        {
            var properties = MemberAccessBindingExpressionVisitor
                             .GetPropertyPath(nonNullExpression, _queryCompilationContext, out var qsre);

            if (properties.Count > 0 &&
                properties[properties.Count - 1] is INavigation lastNavigation &&
                lastNavigation.IsCollection())
            {
                // collection navigation is only null if its parent entity is null (null propagation thru navigation)
                // it is probable that user wanted to see if the collection is (not) empty
                // log warning suggesting to use Any() instead.
                _queryCompilationContext.Logger
                .PossibleUnintendedCollectionNavigationNullComparisonWarning(properties);

                return(Visit(
                           Expression.MakeBinary(
                               nodeType,
                               UnwrapLastNavigation(nonNullExpression),
                               Expression.Constant(null))));
            }

            if (IsInvalidSubQueryExpression(nonNullExpression))
            {
                return(null);
            }

            var entityType = _model.FindEntityType(nonNullExpression.Type)
                             ?? GetEntityType(properties, qsre);

            if (entityType == null)
            {
                return(null);
            }

            var keyProperties = entityType.FindPrimaryKey().Properties;
            var nullCount     = keyProperties.Count;

            Expression keyAccessExpression;

            // Skipping composite key with subquery since it requires to copy subquery
            // which would cause same subquery to be visited twice
            if (nullCount > 1 &&
                nonNullExpression.RemoveConvert() is SubQueryExpression)
            {
                return(null);
            }

            if (properties.Count > 0 &&
                properties[properties.Count - 1] is INavigation navigation2 &&
                navigation2.IsDependentToPrincipal())
            {
                keyAccessExpression = CreateKeyAccessExpression(
                    UnwrapLastNavigation(nonNullExpression),
                    navigation2.ForeignKey.Properties,
                    nullComparison: false);
                nullCount = navigation2.ForeignKey.Properties.Count;
            }
Exemplo n.º 3
0
        /// <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>
        protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
        {
            var newMethodCallExpression = (MethodCallExpression)base.VisitMethodCall(methodCallExpression);

            Expression newLeftExpression  = null;
            Expression newRightExpression = null;

            if (newMethodCallExpression.Method.Name == nameof(object.Equals) &&
                newMethodCallExpression.Object != null &&
                newMethodCallExpression.Arguments.Count == 1)
            {
                newLeftExpression  = newMethodCallExpression.Object;
                newRightExpression = newMethodCallExpression.Arguments[0];
            }

            if (newMethodCallExpression.Method.Equals(_objectEqualsMethodInfo))
            {
                newLeftExpression  = newMethodCallExpression.Arguments[0];
                newRightExpression = newMethodCallExpression.Arguments[1];
            }

            if (newLeftExpression != null &&
                newRightExpression != null)
            {
                var isLeftNullConstant  = newLeftExpression.IsNullConstantExpression();
                var isRightNullConstant = newRightExpression.IsNullConstantExpression();

                if (isLeftNullConstant && isRightNullConstant)
                {
                    return(newMethodCallExpression);
                }

                if (isLeftNullConstant || isRightNullConstant)
                {
                    var result = RewriteNullEquality(
                        ExpressionType.Equal, isLeftNullConstant ? newRightExpression : newLeftExpression);
                    if (result != null)
                    {
                        return(result);
                    }
                }

                var leftEntityType = _model.FindEntityType(newLeftExpression.Type)
                                     ?? MemberAccessBindingExpressionVisitor.GetEntityType(newLeftExpression, _queryCompilationContext);
                var rightEntityType = _model.FindEntityType(newRightExpression.Type)
                                      ?? MemberAccessBindingExpressionVisitor.GetEntityType(newRightExpression, _queryCompilationContext);
                if (leftEntityType != null &&
                    rightEntityType != null)
                {
                    if (leftEntityType.RootType() == rightEntityType.RootType())
                    {
                        var result = RewriteEntityEquality(ExpressionType.Equal, newLeftExpression, newRightExpression);
                        if (result != null)
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        return(Expression.Constant(false));
                    }
                }
            }

            return(newMethodCallExpression);
        }