static PipelineBinder() { __methodCallBinder = new MethodInfoMethodCallBinder <PipelineBindingContext>(); __methodCallBinder.Register(new AnyBinder(), AnyBinder.GetSupportedMethods()); __methodCallBinder.Register(new AverageBinder(), AverageBinder.GetSupportedMethods()); __methodCallBinder.Register(new CountBinder(), CountBinder.GetSupportedMethods()); __methodCallBinder.Register(new DistinctBinder(), DistinctBinder.GetSupportedMethods()); __methodCallBinder.Register(new FirstBinder(), FirstBinder.GetSupportedMethods()); __methodCallBinder.Register(new GroupByBinder(), GroupByBinder.GetSupportedMethods()); __methodCallBinder.Register(new GroupByWithResultSelectorBinder(), GroupByWithResultSelectorBinder.GetSupportedMethods()); __methodCallBinder.Register(new JoinBinder(), JoinBinder.GetSupportedMethods()); __methodCallBinder.Register(new MaxBinder(), MaxBinder.GetSupportedMethods()); __methodCallBinder.Register(new MinBinder(), MinBinder.GetSupportedMethods()); __methodCallBinder.Register(new OfTypeBinder(), OfTypeBinder.GetSupportedMethods()); __methodCallBinder.Register(new OrderByBinder(), OrderByBinder.GetSupportedMethods()); __methodCallBinder.Register(new SampleBinder(), SampleBinder.GetSupportedMethods()); __methodCallBinder.Register(new SelectBinder(), SelectBinder.GetSupportedMethods()); __methodCallBinder.Register(new SelectManyBinder(), SelectManyBinder.GetSupportedMethods()); __methodCallBinder.Register(new SingleBinder(), SingleBinder.GetSupportedMethods()); __methodCallBinder.Register(new SkipBinder(), SkipBinder.GetSupportedMethods()); __methodCallBinder.Register(new StandardDeviationPopulationBinder(), StandardDeviationPopulationBinder.GetSupportedMethods()); __methodCallBinder.Register(new StandardDeviationSampleBinder(), StandardDeviationSampleBinder.GetSupportedMethods()); __methodCallBinder.Register(new SumBinder(), SumBinder.GetSupportedMethods()); __methodCallBinder.Register(new TakeBinder(), TakeBinder.GetSupportedMethods()); __methodCallBinder.Register(new ThenByBinder(), ThenByBinder.GetSupportedMethods()); __methodCallBinder.Register(new WhereBinder(), WhereBinder.GetSupportedMethods()); }
/// <summary> /// Parses an <paramref name="orderBy "/> clause on the given <paramref name="elementType"/>, binding /// the text into semantic nodes using the provided model. /// </summary> /// <param name="orderBy">String representation of the orderby expression.</param> /// <param name="configuration">The configuration used for binding.</param> /// <param name="elementType">Type that the orderby clause refers to.</param> /// <param name="navigationSource">NavigationSource that the elements are from.</param> /// <returns>An <see cref="OrderByClause"/> representing the metadata bound orderby expression.</returns> private OrderByClause ParseOrderByImplementation(string orderBy, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(configuration, "configuration"); ExceptionUtils.CheckArgumentNotNull(configuration.Model, "model"); ExceptionUtils.CheckArgumentNotNull(elementType, "elementType"); ExceptionUtils.CheckArgumentNotNull(orderBy, "orderBy"); // Get the syntactic representation of the orderby expression UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.OrderByLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier); var orderByQueryTokens = expressionParser.ParseOrderBy(orderBy); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource); state.RangeVariables.Push(state.ImplicitRangeVariable); if (applyClause != null) { state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames(); } MetadataBinder binder = new MetadataBinder(state); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); OrderByClause orderByClause = orderByBinder.BindOrderBy(state, orderByQueryTokens); return(orderByClause); }
public void BindOrderByShouldReturnAnOrderByNodeForEachToken() { var metadataBinder = new MetadataBinder(this.bindingState); this.orderbyBinder = new OrderByBinder(metadataBinder.Bind); var tokens = GetDummyOrderbyTokenList(7); var result = orderbyBinder.BindOrderBy(this.bindingState, tokens); Assert.Null(result.ThenBy.ThenBy.ThenBy.ThenBy.ThenBy.ThenBy.ThenBy); }
public void BindOrderByShouldOrderByInEasyToConsumeOrder() { var metadataBinder = new MetadataBinder(this.bindingState); this.orderbyBinder = new OrderByBinder(metadataBinder.Bind); var tokens = GetDummyOrderbyTokenList(2); // $orderby=prop0, prop1 var result = orderbyBinder.BindOrderBy(this.bindingState, tokens); result.Expression.ShouldBeConstantQueryNode("prop0"); result.ThenBy.Expression.ShouldBeConstantQueryNode("prop1"); }
public OrderByBinderTests() { this.orderbyBinder = new OrderByBinder(FakeBindMethods.BindMethodReturningASinglePrimitive); var implicitRangeVariable = new ResourceRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); this.bindingState = new BindingState(configuration) { ImplicitRangeVariable = implicitRangeVariable }; this.bindingState.RangeVariables.Push(new BindingState(configuration) { ImplicitRangeVariable = implicitRangeVariable }.ImplicitRangeVariable); }
public void OrderByBinder_Binds_Throws_InputParameters() { // Arrange IOrderByBinder binder = new OrderByBinder(); // Act & Assert ExceptionAssert.ThrowsArgumentNull(() => binder.BindOrderBy(null, null), "orderByClause"); // Act & Assert SingleValueNode expression = new Mock <SingleValueNode>().Object; RangeVariable range = new Mock <RangeVariable>().Object; OrderByClause orderByClause = new OrderByClause(null, expression, OrderByDirection.Descending, range); ExceptionAssert.ThrowsArgumentNull(() => binder.BindOrderBy(orderByClause, null), "context"); }
private static OrderByBinderResult BindOrderBy <T>(string orderBy, IEdmModel model, ODataQuerySettings querySettings = null, IAssemblyResolver assembliesResolver = null) { Type elementType = typeof(T); OrderByClause orderByClause = CreateOrderByNode(orderBy, model, elementType); Assert.NotNull(orderByClause); querySettings = querySettings ?? _defaultSettings; QueryBinderContext context = new QueryBinderContext(model, querySettings, elementType) { AssembliesResolver = assembliesResolver, }; IOrderByBinder orderByBinder = new OrderByBinder(); return(orderByBinder.BindOrderBy(orderByClause, context)); }
public void OrderByBinder_BindsComputedPropertyInDollarOrderBy_FromDollarCompute() { // Arrange QueryClause clause = CreateQueryClause("$orderby=Total&$compute=Price mul Qty as Total", _model, typeof(ComputeCustomer)); ODataQuerySettings querySettings = new ODataQuerySettings(); IOrderByBinder binder = new OrderByBinder(); QueryBinderContext context = new QueryBinderContext(_model, querySettings, typeof(ComputeCustomer)); if (clause.Compute != null) { context.AddComputedProperties(clause.Compute.ComputedItems); } // Act OrderByBinderResult orderByResult = binder.BindOrderBy(clause.OrderBy, context); // Assert Assert.Null(orderByResult.ThenBy); Assert.Equal(OrderByDirection.Ascending, orderByResult.Direction); string resultExpression = ExpressionStringBuilder.ToString(orderByResult.OrderByExpression); Assert.Equal("$it => ($it.Price * Convert($it.Qty))", resultExpression); IEnumerable <ComputeCustomer> customers = new[] { new ComputeCustomer { Id = 1, Qty = 3, Price = 5.99 }, new ComputeCustomer { Id = 2, Qty = 5, Price = 2.99 }, new ComputeCustomer { Id = 3, Qty = 2, Price = 18.01 }, new ComputeCustomer { Id = 4, Qty = 4, Price = 9.99 }, }; var orderedResult = OrderByBinderTests.InvokeOrderBy(customers, orderByResult.OrderByExpression, orderByResult.Direction, false); Assert.True(new [] { 2, 1, 3, 4 }.SequenceEqual(orderedResult.Select(a => a.Id))); // ordered id }
/// <summary> /// Apply $orderby parameter to query. /// </summary> /// <param name="query"> /// The OData aware query. /// </param> /// <param name="orderbyText"> /// The $orderby parameter text. /// </param> /// <param name="entitySetName"> /// The entity set name. /// </param> /// <typeparam name="T"> /// The query type param /// </typeparam> /// <returns> /// The <see cref="ODataQuery{T}"/> query with applied order by parameter. /// </returns> /// <exception cref="ArgumentNullException"> /// Argument Null Exception /// </exception> public static ODataQueryOrdered <T> OrderBy <T>(this ODataQuery <T> query, string orderbyText, string entitySetName = null) { if (query == null) { throw new ArgumentNullException(nameof(query)); } if (orderbyText == null) { throw new ArgumentNullException(nameof(orderbyText)); } IEdmModel edmModel = query.EdmModel; ODataQueryOptionParser queryOptionParser = GetParser( query, entitySetName, new Dictionary <string, string> { { "$orderby", orderbyText } }); ODataSettings settings = query.ServiceProvider.GetRequiredService <ODataSettings>(); var orderByClause = queryOptionParser.ParseOrderBy(); orderByClause = TranslateParameterAlias(orderByClause, queryOptionParser); ICollection <OrderByNode> nodes = OrderByNode.CreateCollection(orderByClause); var validator = new OrderByQueryValidator(settings.DefaultQuerySettings); validator.Validate(nodes, settings.ValidationSettings, edmModel); IOrderedQueryable <T> result = (IOrderedQueryable <T>)OrderByBinder.OrderApplyToCore(query, settings.QuerySettings, nodes, edmModel); return(new ODataQueryOrdered <T>(result, query.ServiceProvider)); }
/// <summary> /// Generate an expand item based on an ExpandTermToken /// </summary> /// <param name="tokenIn">the expandTerm token to visit</param> /// <returns>the expand item for this expand term token.</returns> private ExpandedNavigationSelectItem GenerateExpandItem(ExpandTermToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); // ensure that we're always dealing with a normalized tree if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified()) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingANonNormalizedTree); } PathSegmentToken currentToken = tokenIn.PathToNavProp; IEdmEntityType currentLevelEntityType = this.entityType; List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>(); PathSegmentToken firstNonTypeToken = currentToken; if (currentToken.IsNamespaceOrContainerQualified()) { pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, ref currentLevelEntityType, out firstNonTypeToken)); } IEdmProperty edmProperty = currentLevelEntityType.FindProperty(firstNonTypeToken.Identifier); if (edmProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullName(), currentToken.Identifier)); } IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty; if (currentNavProp == null) { // the server allowed non-navigation, non-stream properties to be expanded, but then ignored them. if (this.Settings.UseWcfDataServicesServerBehavior && !edmProperty.Type.IsStream()) { return(null); } throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.FullName())); } pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/ null)); ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar); SelectExpandClause subSelectExpand; if (tokenIn.ExpandOption != null) { subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn); } else { subSelectExpand = BuildDefaultSubExpand(); } subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption); IEdmEntitySet targetEntitySet = null; if (this.entitySet != null) { targetEntitySet = this.entitySet.FindNavigationTarget(currentNavProp); } // call MetadataBinder to build the filter clause FilterClause filterOption = null; if (tokenIn.FilterOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetEntitySet); FilterBinder filterBinder = new FilterBinder(binder.Bind, binder.BindingState); filterOption = filterBinder.BindFilter(tokenIn.FilterOption); } // call MetadataBinder again to build the orderby clause OrderByClause orderbyOption = null; if (tokenIn.OrderByOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetEntitySet); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, new OrderByToken[] { tokenIn.OrderByOption }); } return(new ExpandedNavigationSelectItem(pathToNavProp, targetEntitySet, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.InlineCountOption, subSelectExpand)); }