public static Expression BuildOrderExpression( Expression queryExpression, OrderingFields orderingFields) { queryExpression = GetOrderBy(queryExpression, orderingFields.Fields[0]); foreach (OrderingField field in orderingFields.Fields.Skip(1)) { queryExpression = GetThenBy(queryExpression, field); } return(queryExpression); }
public IQueryable <OrderedItem> BuildAfterQuery( IQueryable <TDbObject> query, Expression <Func <TDbObject, TOrder> > orderBy, Expression <Func <TOrder, TOrder, bool> > filter, Expression <Func <TDbObject, TResult> > select, Cursor after) { MemberInitExpression orderedItemInit = Expression.MemberInit( Expression.New(typeof(OrderedItem)), Expression.Bind(OrderMember, ParameterReplacer.RepalceParameter(new SortDirectionRemoverVisitor(orderBy.Body).Expression)), Expression.Bind(ValueMember, ParameterReplacer.RepalceParameter(select.Body))); Expression queryExpression = query.Expression; OrderingFields orderingFields = OrderRequestBuilder.GetOrdering(orderBy); if (_cursorFormatter.HasValue(after)) { TOrder order = _cursorFormatter.ParseAs <TOrder>(after); Expression filterBody = filter != null ? FilterBuilder.RemapFilter(orderedItemInit, filter, order) : FilterBuilder.BuildAutoFilter(orderedItemInit, orderingFields, order); // add where filtration queryExpression = Expression.Call( typeof(Queryable), nameof(Queryable.Where), new System.Type[] { typeof(TDbObject) }, queryExpression, Expression.Lambda <Func <TDbObject, bool> >(filterBody, DbItem)); } // add passed order queryExpression = OrderRequestBuilder.BuildOrderExpression(queryExpression, orderingFields); // extend selection and add order fields queryExpression = Expression.Call( typeof(Queryable), nameof(Queryable.Select), new System.Type[] { typeof(TDbObject), typeof(OrderedItem) }, queryExpression, Expression.Lambda <Func <TDbObject, OrderedItem> >(orderedItemInit, DbItem)); return(query.Provider.CreateQuery <OrderedItem>(queryExpression)); }
public static Expression BuildAutoFilter( Expression mappingExpression, OrderingFields orderingFields, TOrder after) { var filters = new List <FilterValue>(capacity: orderingFields.Fields.Count); foreach (OrderingField field in orderingFields.Fields) { var value = orderingFields.IsDirect ? after : GetValue(after, field); filters.Add(new FilterValue { Expression = field.Expression, Value = Expression.Constant(value), IsLower = field.IsDescending, }); } Expression filter = null; for (var current = 0; current < filters.Count; current++) { FilterValue currentValue = filters[current]; Expression currentFilter = null; for (var prev = 0; prev < current; prev++) { FilterValue prevValue = filters[prev]; Expression equal = Expression.Equal(prevValue.Expression, prevValue.Value); currentFilter = currentFilter != null?Expression.AndAlso(currentFilter, equal) : equal; } Expression compare = GreateCompareExpression(currentValue); currentFilter = currentFilter != null?Expression.AndAlso(currentFilter, compare) : compare; filter = filter != null?Expression.OrElse(filter, currentFilter) : currentFilter; } return(ParameterReplacer.RepalceParameter(filter)); }
public static OrderingFields GetOrdering(Expression <Func <TDbObject, TOrder> > orderBy) { var result = new OrderingFields { OrderParameter = orderBy.Parameters[0] }; result.Fields = (from item in new OrderingMappingVisitor(orderBy).GetMappingList() where item.Member.DeclaringType == typeof(TOrder) let property = (PropertyInfo)item.Member let sortDirection = new SortDirectionVisitor(item.Expression) select new OrderingField { Type = property.PropertyType, Expression = sortDirection.Expression, IsDescending = sortDirection.IsDescending, Property = property, }).ToArray(); // if order is simple direct field access like (item => item.id) if (result.Fields.Count == 0) { var sortDirection = new SortDirectionVisitor(orderBy.Body); result.Fields = new[] { new OrderingField { Type = typeof(TOrder), Expression = sortDirection.Expression, IsDescending = sortDirection.IsDescending, } }; result.IsDirect = true; } return(result); }