private (NavigationExpansionExpression navigationExpression, Expression nullKeyExpression) CreateNullComparisonArguments(
            NavigationBindingExpression navigationBindingExpression,
            NavigationExpansionExpression navigationExpansionExpression)
        {
            var navigationKeyAccessExpression = NavigationExpansionHelpers.CreateKeyAccessExpression(
                navigationBindingExpression,
                new[] { navigationBindingExpression.EntityType.FindPrimaryKey().Properties.First() },
                addNullCheck: true);

            var nullKeyExpression = NavigationExpansionHelpers.CreateNullKeyExpression(
                navigationKeyAccessExpression.Type,
                keyCount: 1);

            var newNavigationExpansionExpressionState = new NavigationExpansionExpressionState(
                navigationExpansionExpression.State.CurrentParameter,
                navigationExpansionExpression.State.SourceMappings,
                Expression.Lambda(navigationKeyAccessExpression, navigationExpansionExpression.State.PendingSelector.Parameters[0]),
                applyPendingSelector: true,
                navigationExpansionExpression.State.PendingOrderings,
                navigationExpansionExpression.State.PendingIncludeChain,
                // we need to remap cardinality reducing operator since it's source type has now changed
                navigationExpansionExpression.State.PendingCardinalityReducingOperator?.GetGenericMethodDefinition().MakeGenericMethod(navigationKeyAccessExpression.Type),
                navigationExpansionExpression.State.CustomRootMappings,
                navigationExpansionExpression.State.MaterializeCollectionNavigation);

            var navigationExpression = new NavigationExpansionExpression(
                navigationExpansionExpression.Operand,
                newNavigationExpansionExpressionState,
                navigationKeyAccessExpression.Type);

            return(navigationExpression, nullKeyExpression);
        }
Пример #2
0
        private Expression TryRewriteNavigationComparison(Expression left, Expression right, bool equality)
        {
            var leftBinding       = left as NavigationBindingExpression;
            var rightBinding      = right as NavigationBindingExpression;
            var leftNullConstant  = left.IsNullConstantExpression();
            var rightNullConstant = right.IsNullConstantExpression();

            Expression newLeft  = null;
            Expression newRight = null;

            // comparing two different collection navigations always returns false
            if (leftBinding != null &&
                rightBinding != null &&
                leftBinding.NavigationTreeNode.Navigation != rightBinding.NavigationTreeNode.Navigation &&
                (leftBinding.NavigationTreeNode.IsCollection || rightBinding.NavigationTreeNode.IsCollection))
            {
                if (leftBinding.NavigationTreeNode.IsCollection)
                {
                    var parentTreeNode = leftBinding.NavigationTreeNode.Parent;
                    parentTreeNode.Children.Remove(leftBinding.NavigationTreeNode);
                }

                if (rightBinding.NavigationTreeNode.IsCollection)
                {
                    var parentTreeNode = rightBinding.NavigationTreeNode.Parent;
                    parentTreeNode.Children.Remove(rightBinding.NavigationTreeNode);
                }

                return(Expression.Constant(false));
            }

            if (leftBinding != null && rightBinding != null &&
                leftBinding.EntityType == rightBinding.EntityType)
            {
                if (leftBinding.NavigationTreeNode.Navigation == rightBinding.NavigationTreeNode.Navigation &&
                    leftBinding.NavigationTreeNode.IsCollection)
                {
                    leftBinding  = CreateParentBindingExpression(leftBinding);
                    rightBinding = CreateParentBindingExpression(rightBinding);
                }

                // TODO: what about entities without PKs?
                var primaryKeyProperties = leftBinding.EntityType.FindPrimaryKey().Properties;
                newLeft  = NavigationExpansionHelpers.CreateKeyAccessExpression(leftBinding, primaryKeyProperties, addNullCheck: leftBinding.NavigationTreeNode.Optional);
                newRight = NavigationExpansionHelpers.CreateKeyAccessExpression(rightBinding, primaryKeyProperties, addNullCheck: rightBinding.NavigationTreeNode.Optional);
            }

            if (leftBinding != null &&
                rightNullConstant)
            {
                if (leftBinding.NavigationTreeNode.IsCollection)
                {
                    leftBinding = CreateParentBindingExpression(leftBinding);
                }

                // TODO: what about entities without PKs?
                var primaryKeyProperties = leftBinding.EntityType.FindPrimaryKey().Properties;
                newLeft  = NavigationExpansionHelpers.CreateKeyAccessExpression(leftBinding, primaryKeyProperties, addNullCheck: leftBinding.NavigationTreeNode.Optional);
                newRight = NavigationExpansionHelpers.CreateNullKeyExpression(newLeft.Type, primaryKeyProperties.Count);
            }

            if (rightBinding != null &&
                leftNullConstant)
            {
                if (rightBinding.NavigationTreeNode.IsCollection)
                {
                    rightBinding = CreateParentBindingExpression(rightBinding);
                }

                // TODO: what about entities without PKs?
                var primaryKeyProperties = rightBinding.EntityType.FindPrimaryKey().Properties;
                newRight = NavigationExpansionHelpers.CreateKeyAccessExpression(rightBinding, primaryKeyProperties, addNullCheck: rightBinding.NavigationTreeNode.Optional);
                newLeft  = NavigationExpansionHelpers.CreateNullKeyExpression(newRight.Type, primaryKeyProperties.Count);
            }

            if (newLeft == null || newRight == null)
            {
                return(null);
            }

            if (newLeft.Type != newRight.Type)
            {
                if (newLeft.Type.IsNullableType())
                {
                    newRight = Expression.Convert(newRight, newLeft.Type);
                }
                else
                {
                    newLeft = Expression.Convert(newLeft, newRight.Type);
                }
            }

            return(equality
                ? Expression.Equal(newLeft, newRight)
                : Expression.NotEqual(newLeft, newRight));
        }