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); }
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); }
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); }
/// <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); }
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)); }
/// <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); }
/// <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()); } }
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); }