protected override Expression VisitMember(MemberExpression memberExpression)
        {
            var newExpression = Visit(memberExpression.Expression);
            var boundProperty = TryBindProperty(memberExpression, newExpression, memberExpression.Member.Name);

            var result = boundProperty ?? memberExpression.Update(newExpression);

            // add null safety when accessing property of optional navigation
            // we don't need to do it for collections (i.e. collection.Count) because they will be converted into subqueries anyway
            if (boundProperty == null &&
                newExpression is NavigationBindingExpression navigationBindingExpression &&
                navigationBindingExpression.NavigationTreeNode.Optional &&
                navigationBindingExpression.NavigationTreeNode.Navigation?.IsCollection() != true)
            {
                var nullProtection = new NullConditionalExpression(newExpression, result);
                if (nullProtection.Type == result.Type)
                {
                    return(nullProtection);
                }

                result = Expression.Convert(nullProtection, memberExpression.Type);
            }

            return(result);
        }
Ejemplo n.º 2
0
        private void VisitNullConditionalExpression(NullConditionalExpression nullConditionalExpression)
        {
            if (nullConditionalExpression.AccessOperation is MemberExpression memberExpression)
            {
                Visit(nullConditionalExpression.Caller);
                _stringBuilder.Append("?." + memberExpression.Member.Name);
            }
            else if (nullConditionalExpression.AccessOperation is MethodCallExpression methodCallExpression)
            {
                if (methodCallExpression.Object != null)
                {
                    Visit(nullConditionalExpression.Caller);
                    _stringBuilder.Append("?." + methodCallExpression.Method.Name + "(");
                    VisitArguments(methodCallExpression.Arguments, s => _stringBuilder.Append(s));
                    _stringBuilder.Append(")");
                }

                var method = methodCallExpression.Method;

                _stringBuilder.Append(method.DeclaringType?.Name + "." + method.Name + "(?");
                Visit(nullConditionalExpression.Caller);
                _stringBuilder.Append("?, ");
                VisitArguments(methodCallExpression.Arguments.Skip(1).ToList(), s => _stringBuilder.Append(s));
                _stringBuilder.Append(")");
            }
            else
            {
                _stringBuilder.Append("?");
                Visit(nullConditionalExpression.AccessOperation);
                _stringBuilder.Append("?");
            }
        }
        private static Expression BuildCollectionAccessorExpression(
            ParameterExpression parameter,
            IEnumerable <IPropertyBase> navigations)
        {
            Expression result           = parameter;
            Expression memberExpression = parameter;

            foreach (var navigation in navigations)
            {
                memberExpression = memberExpression.MakeMemberAccess(navigation.GetIdentifyingMemberInfo());
                result           = new NullConditionalExpression(result, memberExpression);
            }

            return(result);
        }
            private static void ApplyParentOrderings(
                IEnumerable <Ordering> parentOrderings,
                QueryModel queryModel,
                QuerySourceMapping querySourceMapping,
                bool reverseOrdering)
            {
                var orderByClause = queryModel.BodyClauses.OfType <OrderByClause>().LastOrDefault();

                if (orderByClause == null)
                {
                    queryModel.BodyClauses.Add(orderByClause = new OrderByClause());
                }

                foreach (var ordering in parentOrderings)
                {
                    var newExpression
                        = CloningExpressionVisitor
                          .AdjustExpressionAfterCloning(ordering.Expression, querySourceMapping);

                    if (newExpression is MethodCallExpression methodCallExpression &&
                        methodCallExpression.Method.IsEFPropertyMethod())
                    {
                        newExpression
                            = new NullConditionalExpression(
                                  methodCallExpression.Arguments[0],
                                  methodCallExpression.Arguments[0],
                                  methodCallExpression);
                    }

                    orderByClause.Orderings
                    .Add(new Ordering(newExpression, ordering.OrderingDirection));
                }

                if (reverseOrdering)
                {
                    foreach (var ordering in orderByClause.Orderings)
                    {
                        ordering.OrderingDirection
                            = ordering.OrderingDirection == OrderingDirection.Asc
                                ? OrderingDirection.Desc
                                : OrderingDirection.Asc;
                    }
                }
            }