コード例 #1
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);
        }
コード例 #2
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 VisitBinary(BinaryExpression binaryExpression)
        {
            Check.NotNull(binaryExpression, nameof(binaryExpression));

            var newBinaryExpression = (BinaryExpression)base.VisitBinary(binaryExpression);

            if (binaryExpression.NodeType == ExpressionType.Equal ||
                binaryExpression.NodeType == ExpressionType.NotEqual)
            {
                var isLeftNullConstant  = newBinaryExpression.Left.IsNullConstantExpression();
                var isRightNullConstant = newBinaryExpression.Right.IsNullConstantExpression();

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

                var isNullComparison  = isLeftNullConstant || isRightNullConstant;
                var nonNullExpression = isLeftNullConstant ? newBinaryExpression.Right : newBinaryExpression.Left;

                var qsre = nonNullExpression as QuerySourceReferenceExpression;

                var leftProperties = MemberAccessBindingExpressionVisitor.GetPropertyPath(
                    newBinaryExpression.Left, _queryCompilationContext, out var leftNavigationQsre);

                var rightProperties = MemberAccessBindingExpressionVisitor.GetPropertyPath(
                    newBinaryExpression.Right, _queryCompilationContext, out var rightNavigationQsre);

                if (isNullComparison)
                {
                    var nonNullNavigationQsre = isLeftNullConstant ? rightNavigationQsre : leftNavigationQsre;
                    var nonNullproperties     = isLeftNullConstant ? rightProperties : leftProperties;

                    if (IsCollectionNavigation(nonNullNavigationQsre, nonNullproperties))
                    {
                        // 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(nonNullproperties);

                        var callerExpression = CreateCollectionCallerExpression(nonNullNavigationQsre, nonNullproperties);

                        return(Visit(Expression.MakeBinary(newBinaryExpression.NodeType, callerExpression, Expression.Constant(null))));
                    }
                }

                var collectionNavigationComparison = TryRewriteCollectionNavigationComparison(
                    newBinaryExpression.Left,
                    newBinaryExpression.Right,
                    newBinaryExpression.NodeType,
                    leftNavigationQsre,
                    rightNavigationQsre,
                    leftProperties,
                    rightProperties);

                if (collectionNavigationComparison != null)
                {
                    return(collectionNavigationComparison);
                }

                // If a reference navigation is being compared to null then don't rewrite
                if (isNullComparison &&
                    qsre == null)
                {
                    return(newBinaryExpression);
                }

                var entityType = _queryCompilationContext.Model.FindEntityType(nonNullExpression.Type);
                if (entityType == null)
                {
                    if (qsre != null)
                    {
                        entityType = _queryCompilationContext.FindEntityType(qsre.ReferencedQuerySource);
                    }
                    else
                    {
                        entityType = MemberAccessBindingExpressionVisitor.GetEntityType(
                            nonNullExpression, _queryCompilationContext);
                    }
                }

                if (entityType != null)
                {
                    return(CreateKeyComparison(
                               entityType,
                               newBinaryExpression.Left,
                               newBinaryExpression.Right,
                               newBinaryExpression.NodeType,
                               isLeftNullConstant,
                               isRightNullConstant,
                               isNullComparison));
                }
            }

            return(newBinaryExpression);
        }