/// <summary>
        /// Translates an OData $orderby represented by <see cref="OrderByClause"/> to <see cref="Expression"/> and apply to <see cref="IQueryable" />.
        /// </summary>
        /// <param name="binder">The given filter binder.</param>
        /// <param name="query">The given source.</param>
        /// <param name="orderByClause">The filter clause.</param>
        /// <param name="context">The query binder context.</param>
        /// <param name="alreadyOrdered">The boolean value indicating whether it's ordered or not.</param>
        /// <returns>The applied result.</returns>
        public static IQueryable ApplyBind(this IOrderByBinder binder, IQueryable query, OrderByClause orderByClause, QueryBinderContext context, bool alreadyOrdered)
        {
            if (binder == null)
            {
                throw Error.ArgumentNull(nameof(binder));
            }

            if (query == null)
            {
                throw Error.ArgumentNull(nameof(query));
            }

            if (orderByClause == null)
            {
                throw Error.ArgumentNull(nameof(orderByClause));
            }

            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            OrderByBinderResult orderByResult = binder.BindOrderBy(orderByClause, context);
            IQueryable          querySoFar    = query;

            Type elementType           = context.ElementClrType;
            OrderByBinderResult result = orderByResult;

            do
            {
                LambdaExpression orderByExpression = result.OrderByExpression as LambdaExpression;
                Contract.Assert(orderByExpression != null);

                OrderByDirection direction = result.Direction;

                querySoFar = ExpressionHelpers.OrderBy(querySoFar, orderByExpression, direction, elementType, alreadyOrdered);

                alreadyOrdered = true;

                result = result.ThenBy;
            }while (result != null);

            return(querySoFar);
        }
Example #2
0
        /// <summary>
        /// Translates an OData $orderby represented by <see cref="OrderByClause"/> to <see cref="Expression"/>.
        /// $orderby=Age
        ///    |--  x => x.Age
        /// </summary>
        /// <param name="orderByClause">The orderby clause.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The OrderBy binder result, <see cref="OrderByBinderResult"/>.</returns>
        public virtual OrderByBinderResult BindOrderBy(OrderByClause orderByClause, QueryBinderContext context)
        {
            if (orderByClause == null)
            {
                throw Error.ArgumentNull(nameof(orderByClause));
            }

            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            OrderByBinderResult head = null;
            OrderByBinderResult last = null;

            for (OrderByClause clause = orderByClause; clause != null; clause = clause.ThenBy)
            {
                Expression body = Bind(clause.Expression, context);

                ParameterExpression parameter = context.CurrentParameter;

                LambdaExpression orderByLambda = Expression.Lambda(body, parameter);

                OrderByBinderResult result = new OrderByBinderResult(orderByLambda, clause.Direction);

                if (head == null)
                {
                    head = result;
                    last = result;
                }
                else
                {
                    Contract.Assert(last != null);
                    last.ThenBy = result;
                    last        = result;
                }
            }

            return(head);
        }