public static IQueryable<TElement> Apply<TElement>(IQueryable<TElement> query, ODataQueryExpression oDataQuery, out IQueryable<TElement> inlineCountQuery)
        {
            var finalQuery = query;

            if (oDataQuery.Filter != null)
            {
                var parameter = Expression.Parameter(typeof(TElement));
                var predicate = Expression.Lambda<Func<TElement, bool>>(Translate(parameter, oDataQuery.Filter), parameter);
                var denormalizedPredicate = (Expression<Func<TElement, bool>>)ODataEntity.Denormalize(predicate);
                finalQuery = finalQuery.Where(denormalizedPredicate);
            }

            inlineCountQuery = finalQuery;

            for (var i = 0; i < oDataQuery.OrderBy.Count; ++i)
            {
                finalQuery = ApplyOrderBy(finalQuery, oDataQuery.OrderBy[i], isPrimarySort: i == 0);
            }

            if (oDataQuery.Skip > 0)
            {
                finalQuery = finalQuery.Skip(oDataQuery.Skip);
            }

            if (oDataQuery.Top.HasValue)
            {
                finalQuery = finalQuery.Take(oDataQuery.Top.Value);
            }

            return finalQuery;
        }
        private static IQueryable<TElement> ApplyOrderBy<TElement>(IQueryable<TElement> query, ODataSortKeyExpression sortKey, bool isPrimarySort)
        {
            var parameter = Expression.Parameter(typeof(TElement));
            var translated = Translate(parameter, sortKey.Expression);
            var lambda = Expression.Lambda(translated, parameter);

            var methodName = (isPrimarySort ? "OrderBy" : "ThenBy") + (sortKey.Descending ? "Descending" : string.Empty);
            MethodInfo method;
            switch (methodName)
            {
                case "OrderBy":
                    method = Helpers.GetMethod((IQueryable<object> q) => q.OrderBy(o => o));
                    break;
                case "OrderByDescending":
                    method = Helpers.GetMethod((IQueryable<object> q) => q.OrderByDescending(o => o));
                    break;
                case "ThenBy":
                    method = Helpers.GetMethod((IOrderedQueryable<object> q) => q.ThenBy(o => o));
                    break;
                case "ThenByDescending":
                    method = Helpers.GetMethod((IOrderedQueryable<object> q) => q.ThenByDescending(o => o));
                    break;
                default:
                    throw Throw.UnexpectedCase(methodName);
            }

            var denormalizedLambda = ODataEntity.Denormalize(lambda);
            var result = method.GetGenericMethodDefinition()
                .MakeGenericMethod(lambda.Type.GetGenericArguments(typeof(Func<,>)))
                .Invoke(null, new object[] { query, denormalizedLambda });
            return (IQueryable<TElement>)result;
        }
示例#3
0
        public static Result Project(IQueryable query, IReadOnlyList <ODataSelectColumnExpression> select)
        {
            if (select.Count == 0)
            {
                return(Project(query, new[] { ODataExpression.SelectStar() }));
            }

            Throw <NotSupportedException> .If(select.Any(sc => !sc.AllColumns && sc.Type == ODataExpressionType.Complex), "Selecting a complex type is only supported when selecting all columns of that type (with '/*')");

            var mapping = BuildMapping(select);

            var parameter     = Expression.Parameter(query.ElementType);
            var newExpression = BuildNewExpression(parameter, mapping);
            var lambda        = Expression.Lambda(newExpression, parameter);
            var selectMethod  = Helpers.GetMethod((IQueryable <object> q) => q.Select(o => o))
                                .GetGenericMethodDefinition()
                                .MakeGenericMethod(query.ElementType, newExpression.Type);
            var denormalizedLambda = ODataEntity.Denormalize(lambda);
            var projected          = (IQueryable)selectMethod.Invoke(null, new object[] { query, denormalizedLambda });

            var resultMapping = BuildResultMapping(projected.ElementType, mapping);

            return(new Result(projected, resultMapping));
        }