예제 #1
0
        private static MethodInfo GetOrderByMethod(bool isThenBy, bool isDesc, Type elementType, Type nextExprType)
        {
            MethodInfo orderByMethod;

            if (isThenBy)
            {
                orderByMethod = isDesc
                          ? TypeFns.GetMethodByExample(
                    (IOrderedQueryable <String> q) => q.ThenByDescending(s => s.Length),
                    elementType, nextExprType)
                          : TypeFns.GetMethodByExample(
                    (IOrderedQueryable <String> q) => q.ThenBy(s => s.Length),
                    elementType, nextExprType);
            }
            else
            {
                orderByMethod = isDesc
                          ? TypeFns.GetMethodByExample(
                    (IQueryable <String> q) => q.OrderByDescending(s => s.Length),
                    elementType, nextExprType)
                          : TypeFns.GetMethodByExample(
                    (IQueryable <String> q) => q.OrderBy(s => s.Length),
                    elementType, nextExprType);
            }
            return(orderByMethod);
        }
예제 #2
0
        private static Func <IQueryable, IQueryable> BuildFilterFunc(string filterQueryString, Type elementType)
        {
            var lambdaExpr = __builder.Parse(elementType, filterQueryString);
            var method     = TypeFns.GetMethodByExample((IQueryable <String> q) => q.Where(s => true), elementType);
            var func       = BuildIQueryableFunc(elementType, method, lambdaExpr);

            return(func);
        }
예제 #3
0
        public static Func <IQueryable, IQueryable> BuildSelectFunc(Type elementType, List <String> selectClauses)
        {
            var propSigs   = selectClauses.Select(sc => new PropertySignature(elementType, sc)).ToList();
            var dti        = DynamicTypeInfo.FindOrCreate(propSigs.Select(ps => ps.Name), propSigs.Select(ps => ps.ReturnType));
            var lambdaExpr = CreateNewLambda(dti, propSigs);
            var method     = TypeFns.GetMethodByExample((IQueryable <String> q) => q.Select(s => s.Length), elementType, dti.DynamicType);
            var func       = BuildIQueryableFunc(elementType, method, lambdaExpr);

            return(func);
        }
예제 #4
0
        /// <summary>
        /// Apply the queryOptions to the query.
        /// This method handles nested order-by statements the the current ASP.NET web api does not yet support.
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="queryOptions"></param>
        /// <param name="querySettings"></param>
        /// <returns></returns>
        public static IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions, ODataQuerySettings querySettings)
        {
            // if we see an extended order by we also need to process any skip/take operators as well.
            var orderByQueryString = queryOptions.RawValues.OrderBy;

            if (orderByQueryString == null || orderByQueryString.IndexOf('/') < 0)
            {
                // Just let the default implementation handle it.
                return(queryOptions.ApplyTo(queryable, querySettings));
            }

            var newQueryOptions = QueryHelper.RemoveExtendedOps(queryOptions);

            var result = QueryHelper.ApplyQuery(queryable, newQueryOptions, querySettings);

            var elementType = TypeFns.GetElementType(queryable.GetType());

            var orderByClauses = orderByQueryString.Split(',').ToList();
            var isThenBy       = false;

            orderByClauses.ForEach(obc =>
            {
                var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, obc);
                result   = func(result);
                isThenBy = true;
            });

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }
            return(result);
        }
예제 #5
0
        protected virtual Expression VisitAnyAll(ParseTreeNode node, Expression targetExpr, String methodName, Expression lambdaExpr)
        {
            var        targetType = targetExpr.Type;
            var        itemType   = TypeFns.GetElementType(targetType);
            MethodInfo methodInfo;

            if (methodName == "any")
            {
                methodInfo = TypeFns.GetMethodByExample((IEnumerable <String> s) => s.Any(s1 => s1.Any()), itemType);
            }
            else
            {
                methodInfo = TypeFns.GetMethodByExample((IEnumerable <String> s) => s.All(s1 => s1.Any()), itemType);
            }
            return(Expression.Call(methodInfo, targetExpr, lambdaExpr));
        }
예제 #6
0
        /// <summary>
        /// Apply the queryOptions to the query.
        /// This method handles nested order-by statements the the current ASP.NET web api does not yet support.
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="queryOptions"></param>
        /// <param name="querySettings"></param>
        /// <returns></returns>
        public static IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions, ODataQuerySettings querySettings)
        {
            // if we see an extended order by we also need to process any skip/take operators as well.
            var orderByQueryString = queryOptions.RawValues.OrderBy;

            // HACK: this is a hack because on a bug in querySettings.EnsureStableOrdering = true that overrides
            // any existing order by clauses, instead of appending to them.
            querySettings.EnsureStableOrdering = false;
            if (orderByQueryString == null || orderByQueryString.IndexOf('/') < 0)
            {
                // Just let the default implementation handle it.
                return(queryOptions.ApplyTo(queryable, querySettings));
            }

            var newQueryOptions = QueryHelper.RemoveExtendedOps(queryOptions);

            var result = QueryHelper.ApplyQuery(queryable, newQueryOptions, querySettings);

            var elementType = TypeFns.GetElementType(queryable.GetType());

            string inlinecountString = queryOptions.RawValues.InlineCount;

            if (!string.IsNullOrWhiteSpace(inlinecountString))
            {
                if (inlinecountString == "allpages")
                {
                    if (result is IQueryable)
                    {
                        var inlineCount = (Int64)Queryable.Count((dynamic)result);
                        queryOptions.Request.SetInlineCount(inlineCount);
                    }
                }
            }

            var orderByClauses = orderByQueryString.Split(',').ToList();
            var isThenBy       = false;

            orderByClauses.ForEach(obc => {
                var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, obc);
                result   = func(result);
                isThenBy = true;
            });

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }



            return(result);
        }
예제 #7
0
        /// <summary>
        /// Called when the action is executed.
        /// </summary>
        /// <param name="actionExecutedContext">The action executed context.</param>
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (actionExecutedContext.Response == null)
            {
                return;
            }

            if (!actionExecutedContext.Response.IsSuccessStatusCode)
            {
                return;
            }

            object responseObject;

            if (!actionExecutedContext.Response.TryGetContentValue(out responseObject))
            {
                return;
            }

            var dQuery = ((dynamic)responseObject);

            if (dQuery.GetType().IsInstanceOfType(typeof(IQueryable)))
            {
                return;
            }

            var elementType = TypeFns.GetElementType(responseObject.GetType());

            NameValueCollection querystringParams =
                HttpUtility.ParseQueryString(actionExecutedContext.Request.RequestUri.Query);

            string filterQueryString = querystringParams["$filter"];

            if (!string.IsNullOrWhiteSpace(filterQueryString))
            {
                var func = BuildFilterFunc(filterQueryString, elementType);
                dQuery = func(dQuery as IQueryable);
            }

            int?   inlineCount       = null;
            string inlinecountString = querystringParams["$inlinecount"];

            if (!string.IsNullOrWhiteSpace(inlinecountString))
            {
                if (inlinecountString == "allpages")
                {
                    if (dQuery is IQueryable)
                    {
                        inlineCount = Queryable.Count(dQuery);
                    }
                }
            }


            string orderByQueryString = querystringParams["$orderby"];

            if (!string.IsNullOrWhiteSpace(orderByQueryString))
            {
                var orderByClauses = orderByQueryString.Split(',').ToList();
                var isThenBy       = false;
                orderByClauses.ForEach(obc => {
                    var func = BuildOrderByFunc(isThenBy, elementType, obc);
                    dQuery   = func(dQuery as IQueryable);
                    isThenBy = true;
                });
            }

            string skipQueryString = querystringParams["$skip"];

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                dQuery = func(dQuery as IQueryable);
            }

            string topQueryString = querystringParams["$top"];

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                dQuery = func(dQuery as IQueryable);
            }

            string selectQueryString = querystringParams["$select"];

            if (!string.IsNullOrWhiteSpace(selectQueryString))
            {
                var selectClauses = selectQueryString.Split(',').Select(sc => sc.Replace('/', '.')).ToList();
                var func          = BuildSelectFunc(elementType, selectClauses);
                dQuery = func(dQuery as IQueryable);
            }

            string expandsQueryString = querystringParams["$expand"];

            if (!string.IsNullOrWhiteSpace(expandsQueryString))
            {
                if (!string.IsNullOrWhiteSpace(selectQueryString))
                {
                    throw new Exception("Use of both 'expand' and 'select' in the same query is not currently supported");
                }
                expandsQueryString.Split(',').Select(s => s.Trim()).ToList().ForEach(expand => {
                    dQuery = dQuery.Include(expand.Replace('/', '.'));
                });
            }

            // execute any DbQueries here, so that any exceptions thrown can be properly returned.
            // if we wait to have the query executed within the serializer, some exceptions will not
            // serialize properly.
            Object rQuery;

            if (dQuery is IQueryable)
            {
                rQuery = System.Linq.Enumerable.ToList((dynamic)dQuery);
            }
            else
            {
                rQuery = dQuery;
            }

            var formatter = ((dynamic)actionExecutedContext.Response.Content).Formatter;
            var oc        = new System.Net.Http.ObjectContent(rQuery.GetType(), rQuery, formatter);

            actionExecutedContext.Response.Content = oc;

            if (inlineCount.HasValue)
            {
                actionExecutedContext.Response.Headers.Add("X-InlineCount", inlineCount.ToString());
            }
        }
예제 #8
0
        private IQueryable ApplyExtendedOrderBy(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            // if we see an extended order by we also need to process any skip/take operators as well.
            var orderByQueryString = queryOptions.RawValues.OrderBy;

            if (orderByQueryString == null || orderByQueryString.IndexOf("/") == -1)
            {
                return(null);
            }

            var request  = queryOptions.Request;
            var oldUri   = request.RequestUri;
            var map      = oldUri.ParseQueryString();
            var newQuery = map.Keys.Cast <String>()
                           .Where(k => (k != "$orderby") && (k != "$top") && (k != "$skip"))
                           .Select(k => k + "=" + map[k])
                           .ToAggregateString("&");

            var newUrl = oldUri.Scheme + "://" + oldUri.Authority + oldUri.AbsolutePath + "?" + newQuery;

            var newRequest = new HttpRequestMessage(request.Method, new Uri(newUrl));
            var newQo      = new ODataQueryOptions(queryOptions.Context, newRequest);
            var result     = base.ApplyQuery(queryable, newQo);

            var elementType = TypeFns.GetElementType(queryable.GetType());


            if (!string.IsNullOrWhiteSpace(orderByQueryString))
            {
                var orderByClauses = orderByQueryString.Split(',').ToList();
                var isThenBy       = false;
                orderByClauses.ForEach(obc => {
                    var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, obc);
                    result   = func(result);
                    isThenBy = true;
                });
            }

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            request.Properties.Add("breeze_orderBy", true);
            return(result);
        }