// GET: odata/Images
        public PageResult<Image> GetImages(ODataQueryOptions<Image> options)
        {
            ODataQuerySettings settings = new ODataQuerySettings()
            {
                PageSize = CollectionOfWorkers.SizeOfPage
            };

            IQueryable results = options.ApplyTo(db.Images.AsQueryable(), settings);

            return new PageResult<Image>(
                results as IEnumerable<Image>,
                null,
                db.Images.Count());
        }
 /// <summary>
 /// Initialize a new instance of the <see cref="ODataQuerySettings"/> class based on an existing one. 
 /// </summary>
 /// <param name="settings">The setting to copy from.</param>
 public ODataQuerySettings(ODataQuerySettings settings)
 {
     EnsureStableOrdering = settings.EnsureStableOrdering;
     EnableConstantParameterization = settings.EnableConstantParameterization;
     HandleNullPropagation = settings.HandleNullPropagation;
     PageSize = settings.PageSize;
 }
        // Pass ODataQueryOptions as parameter, and call validation manually
        public IHttpActionResult GetFromManager(ODataQueryOptions<Manager> queryOptions)
        {
            if (queryOptions.SelectExpand != null)
            {
                queryOptions.SelectExpand.LevelsMaxLiteralExpansionDepth = 5;
            }

            var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 };

            try
            {
                queryOptions.Validate(validationSettings);
            }
            catch (ODataException e)
            {
                var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                responseMessage.Content = new StringContent(
                    string.Format("The query specified in the URI is not valid. {0}", e.Message));
                return ResponseMessage(responseMessage);
            }

            var querySettings = new ODataQuerySettings();
            var result = queryOptions.ApplyTo(_employees.OfType<Manager>().AsQueryable(), querySettings).AsQueryable();
            return Ok(result, result.GetType());
        }
        public void Ctor_Initializes_All_Properties()
        {
            // Arrange & Act
            ODataQuerySettings querySettings = new ODataQuerySettings();

            // Assert
            Assert.Equal(HandleNullPropagationOption.Default, querySettings.HandleNullPropagation);
            Assert.True(querySettings.EnsureStableOrdering);
        }
Beispiel #5
0
        // GET: Domains
        public IEnumerable<DomainsProjection> Get(ODataQueryOptions<DomainsProjection> options)
        {
            var querySettings = new ODataQuerySettings()
            {
                EnableConstantParameterization = true,
                EnsureStableOrdering = true
            };

            var raw = GetDomains().OrderBy(d => d.HostName);
            var total = options.Filter == null ? raw.Count() : options.Filter.ApplyTo(raw, querySettings).Count();
            var res = (IQueryable<DomainsProjection>) options.ApplyTo(raw, querySettings);

            return new PageResult<DomainsProjection>(res, options.GetNextLink(total), total);

            //return GetDomains().ToArray();
        }
 /// <summary>
 /// Applies the $select and $expand query options to the given entity using the given <see cref="ODataQuerySettings"/>.
 /// </summary>
 /// <param name="entity">The original entity.</param>
 /// <param name="settings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
 /// <returns>The new entity after the $select and $expand query has been applied to.</returns>
 public object ApplyTo(object entity, ODataQuerySettings settings)
 {
     return ApplyTo(entity, settings, _defaultAssembliesResolver);
 }
        public void ApplyTo_Does_Not_Replace_Original_OrderBy_With_Missing_Keys()
        {
            // Arrange
            var model = ODataModelBuilderMocks.GetModelBuilderMock<ODataModelBuilder>()
                            .Add_Customers_No_Keys_EntitySet().GetEdmModel();

            var message = new HttpRequestMessage(
                HttpMethod.Get,
                new Uri("http://server/service/Customers?$orderby=Name")
            );

            // Act
            var queryOptions = new ODataQueryOptions(new ODataQueryContext(model, typeof(Customer)), message);
            OrderByQueryOption originalOption = queryOptions.OrderBy;
            ODataQuerySettings querySettings = new ODataQuerySettings();

            IQueryable finalQuery = queryOptions.ApplyTo(new Customer[0].AsQueryable(), querySettings);

            // Assert
            Assert.ReferenceEquals(originalOption, queryOptions.OrderBy);
        }
        private IQueryable GetQuery()
        {
            ODataPath path = this.GetPath();

            RestierQueryBuilder builder = new RestierQueryBuilder(this.Api, path);
            IQueryable queryable = builder.BuildQuery();
            this.shouldReturnCount = builder.IsCountPathSegmentPresent;
            this.shouldWriteRawValue = builder.IsValuePathSegmentPresent;
            if (queryable == null)
            {
                throw new HttpResponseException(
                    this.Request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Resources.ResourceNotFound));
            }

            if (this.shouldReturnCount || this.shouldWriteRawValue)
            {
                // Query options don't apply to $count or $value.
                return queryable;
            }

            ODataQueryContext queryContext =
                new ODataQueryContext(this.Request.ODataProperties().Model, queryable.ElementType, path);
            ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, this.Request);

            // TODO GitHubIssue#41 : Ensure stable ordering for query
            ODataQuerySettings settings = new ODataQuerySettings()
            {
                HandleNullPropagation = HandleNullPropagationOption.False,
                EnsureStableOrdering = true,
                EnableConstantParameterization = false,
                PageSize = null,  // no support for server enforced PageSize, yet
            };

            queryable = queryOptions.ApplyTo(queryable, settings);

            return queryable;
        }
            public IHttpActionResult Get(ODataQueryOptions<LevelsEntity> queryOptions)
            {
                var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 };

                try
                {
                    queryOptions.Validate(validationSettings);
                }
                catch (ODataException e)
                {
                    var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
                    responseMessage.Content = new StringContent(
                        Error.Format("The query specified in the URI is not valid. {0}", e.Message));
                    return ResponseMessage(responseMessage);
                }

                var querySettings = new ODataQuerySettings();
                var result = queryOptions.ApplyTo(Entities.AsQueryable(), querySettings).AsQueryable();
                return Ok(result, result.GetType());
            }
        public IQueryable ApplyTo(IQueryable queryable, ODataQuerySettings settings)
        {
            if (queryable == null)
            {
                throw Error.ArgumentNull("queryable");
            }
            if (settings == null)
            {
                throw Error.ArgumentNull("settings");
            }
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            // Ensure we have decided how to handle null propagation
            ODataQuerySettings updatedSettings = settings;
            if (settings.HandleNullPropagation == HandleNullPropagationOption.Default)
            {
                updatedSettings = new ODataQuerySettings(updatedSettings);
                updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(queryable);
            }

            return SelectExpandBinder.Bind(queryable, updatedSettings, this);
        }
Beispiel #11
0
        private IQueryable GetQuery()
        {
            ODataPath path = this.GetPath();

            RestierQueryBuilder builder = new RestierQueryBuilder(this.Api, path);
            IQueryable queryable = builder.BuildQuery();
            this.shouldReturnCount = builder.IsCountPathSegmentPresent;
            this.shouldWriteRawValue = builder.IsValuePathSegmentPresent;
            if (queryable == null)
            {
                throw new HttpResponseException(
                    this.Request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Resources.ResourceNotFound));
            }

            if (this.shouldReturnCount || this.shouldWriteRawValue)
            {
                // Query options don't apply to $count or $value.
                return queryable;
            }

            ODataQueryContext queryContext =
                new ODataQueryContext(this.Request.ODataProperties().Model, queryable.ElementType, path);
            ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, this.Request);
            if (queryOptions.Count != null)
            {
                this.includeTotalCount = queryOptions.Count.Value;
            }

            // TODO GitHubIssue#41 : Ensure stable ordering for query
            ODataQuerySettings settings = new ODataQuerySettings
            {
                HandleNullPropagation = HandleNullPropagationOption.False,
                PageSize = null,  // no support for server enforced PageSize, yet
            };

            // Entity count can NOT be evaluated at this point of time because the source
            // expression is just a placeholder to be replaced by the expression sourcer.
            queryable = queryOptions.ApplyTo(queryable, settings, AllowedQueryOptions.Count);

            return queryable;
        }
 /// <summary>
 /// Apply the individual query to the given IQueryable in the right order.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>.</param>
 /// <param name="querySettings">The settings to use in query composition.</param>
 /// <returns>The new <see cref="IQueryable"/> after the query has been applied to.</returns>
 public override IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     ValidateQuery(query);
     return(base.ApplyTo(query, querySettings));
 }
        /// <summary>
        /// Apply the filter query to the given IQueryable.
        /// </summary>
        /// <remarks>
        /// The <see cref="ODataQuerySettings.HandleNullPropagation"/> property specifies
        /// how this method should handle null propagation.
        /// </remarks>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <param name="querySettings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
        /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param>
        /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }
            if (querySettings == null)
            {
                throw Error.ArgumentNull("querySettings");
            }
            if (assembliesResolver == null)
            {
                throw Error.ArgumentNull("assembliesResolver");
            }
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            FilterClause filterClause = FilterClause;
            Contract.Assert(filterClause != null);

            // Ensure we have decided how to handle null propagation
            ODataQuerySettings updatedSettings = querySettings;
            if (querySettings.HandleNullPropagation == HandleNullPropagationOption.Default)
            {
                updatedSettings = new ODataQuerySettings(updatedSettings);
                updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query);
            }

            Expression filter = FilterBinder.Bind(filterClause, Context.ElementClrType, Context.Model, assembliesResolver, updatedSettings);
            query = ExpressionHelpers.Where(query, filter, Context.ElementClrType);
            return query;
        }
Beispiel #14
0
        private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
        {
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            ICollection <OrderByNode> nodes = OrderByNodes;

            bool       alreadyOrdered = false;
            IQueryable querySoFar     = query;

            HashSet <IEdmProperty> propertiesSoFar = new HashSet <IEdmProperty>();
            bool orderByItSeen = false;

            foreach (OrderByNode node in nodes)
            {
                OrderByPropertyNode propertyNode = node as OrderByPropertyNode;

                if (propertyNode != null)
                {
                    IEdmProperty     property  = propertyNode.Property;
                    OrderByDirection direction = propertyNode.Direction;

                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (propertiesSoFar.Contains(property))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, property.Name));
                    }
                    propertiesSoFar.Add(property);

                    if (propertyNode.OrderByClause != null)
                    {
                        // Ensure we have decided how to handle null propagation
                        ODataQuerySettings updatedSettings = querySettings;
                        if (querySettings.HandleNullPropagation == HandleNullPropagationOption.Default)
                        {
                            updatedSettings = new ODataQuerySettings(updatedSettings);
                            updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query);
                        }

                        LambdaExpression orderByExpression =
                            FilterBinder.Bind(propertyNode.OrderByClause, Context.ElementClrType, Context.Model, updatedSettings);
                        querySoFar = ExpressionHelpers.OrderBy(querySoFar, orderByExpression, direction, Context.ElementClrType, alreadyOrdered);
                    }
                    else
                    {
                        querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, property, direction, Context.ElementClrType, alreadyOrdered);
                    }
                    alreadyOrdered = true;
                }
                else
                {
                    // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows
                    if (orderByItSeen)
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt));
                    }

                    querySoFar     = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered);
                    alreadyOrdered = true;
                    orderByItSeen  = true;
                }
            }

            return(querySoFar as IOrderedQueryable);
        }
Beispiel #15
0
        private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
        {
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            ICollection <OrderByNode> nodes = OrderByNodes;

            bool       alreadyOrdered = false;
            IQueryable querySoFar     = query;

            HashSet <string> propertiesSoFar = new HashSet <string>();
            bool             orderByItSeen   = false;

            foreach (OrderByNode node in nodes)
            {
                OrderByPropertyNode     propertyNode     = node as OrderByPropertyNode;
                OrderByOpenPropertyNode openPropertyNode = node as OrderByOpenPropertyNode;

                if (propertyNode != null)
                {
                    IEdmProperty     property  = propertyNode.Property;
                    OrderByDirection direction = propertyNode.Direction;

                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (propertiesSoFar.Contains(property.Name))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, property.Name));
                    }
                    propertiesSoFar.Add(property.Name);

                    if (propertyNode.OrderByClause != null)
                    {
                        querySoFar = AddOrderByQueryForProperty(query, querySettings, propertyNode.OrderByClause, querySoFar, direction, alreadyOrdered);
                    }
                    else
                    {
                        querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, property, direction, Context.ElementClrType, alreadyOrdered);
                    }
                    alreadyOrdered = true;
                }
                else if (openPropertyNode != null)
                {
                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (propertiesSoFar.Contains(openPropertyNode.PropertyName))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, openPropertyNode.PropertyName));
                    }
                    propertiesSoFar.Add(openPropertyNode.PropertyName);
                    Contract.Assert(openPropertyNode.OrderByClause != null);
                    querySoFar     = AddOrderByQueryForProperty(query, querySettings, openPropertyNode.OrderByClause, querySoFar, openPropertyNode.Direction, alreadyOrdered);
                    alreadyOrdered = true;
                }
                else
                {
                    // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows
                    if (orderByItSeen)
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt));
                    }

                    querySoFar     = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered);
                    alreadyOrdered = true;
                    orderByItSeen  = true;
                }
            }

            return(querySoFar as IOrderedQueryable);
        }
        public IHttpActionResult Get(int key, ODataQueryOptions<Employee> options)
        {
            if (options.SelectExpand != null)
            {
                options.SelectExpand.LevelsMaxLiteralExpansionDepth = 3;
            }

            var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 3 };

            try
            {
                options.Validate(validationSettings);
            }
            catch (ODataException e)
            {
                HttpResponseMessage resoponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, e.Message, e);
                return ResponseMessage(resoponse);
            }

            var querySettings = new ODataQuerySettings();
            Employee employee = _employees.Single(e => e.ID == key);
            var result = options.ApplyTo(employee, new ODataQuerySettings());
            Type type = result.GetType();
            return Ok(result, type);

        }
Beispiel #17
0
        /// <summary>
        /// Apply the individual query to the given IQueryable in the right order.
        /// </summary>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <param name="querySettings">The settings to use in query composition.</param>
        /// <returns>The new <see cref="IQueryable"/> after the query has been applied to.</returns>
        public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

            if (querySettings == null)
            {
                throw Error.ArgumentNull("querySettings");
            }

            IQueryable result = query;

            // Construct the actual query and apply them in the following order: filter, orderby, skip, top
            if (Filter != null)
            {
                result = Filter.ApplyTo(result, querySettings, _assembliesResolver);
            }

            if (Apply != null)
            {
                result = Apply.ApplyTo(result, querySettings, _assembliesResolver, _aggregationWindowSize);
                UpdateOtherQueryOptions(result);
            }

            if (Count != null && Request.ODataProperties().TotalCount == null)
            {
                long?count = Count.GetEntityCount(result);
                if (count.HasValue)
                {
                    Request.ODataProperties().TotalCount = count.Value;
                }
            }

            OrderByQueryOption orderBy = OrderBy;

            // $skip or $top require a stable sort for predictable results.
            // Result limits require a stable sort to be able to generate a next page link.
            // If either is present in the query and we have permission,
            // generate an $orderby that will produce a stable sort.
            if ((Apply == null) && querySettings.EnsureStableOrdering && (Skip != null || Top != null || querySettings.PageSize.HasValue))
            {
                // If there is no OrderBy present, we manufacture a default.
                // If an OrderBy is already present, we add any missing
                // properties necessary to make a stable sort.
                // Instead of failing early here if we cannot generate the OrderBy,
                // let the IQueryable backend fail (if it has to).
                orderBy = orderBy == null
                            ? GenerateDefaultOrderBy(Context)
                            : EnsureStableSortOrderBy(orderBy, Context);
            }

            if (orderBy != null)
            {
                result = orderBy.ApplyTo(result, querySettings);
            }

            if (Skip != null)
            {
                result = Skip.ApplyTo(result, querySettings);
            }

            if (Top != null)
            {
                result = Top.ApplyTo(result, querySettings);
            }

            if (SelectExpand != null)
            {
                Request.ODataProperties().SelectExpandClause = SelectExpand.SelectExpandClause;
                result = SelectExpand.ApplyTo(result, querySettings);
            }

            if (querySettings.PageSize.HasValue)
            {
                bool resultsLimited;
                result = LimitResults(result, querySettings.PageSize.Value, out resultsLimited);
                if (resultsLimited && Request.RequestUri != null && Request.RequestUri.IsAbsoluteUri && Request.ODataProperties().NextLink == null)
                {
                    Uri nextPageLink = GetNextPageLink(Request, querySettings.PageSize.Value);
                    Request.ODataProperties().NextLink = nextPageLink;
                }
            }

            return(result);
        }
        public void ApplyTo_NestedProperties_DoesNotHandleNullPropagation_IfExplicitInSettings()
        {
            // Arrange
            var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel();
            var orderByOption = new OrderByQueryOption("Address/City asc", new ODataQueryContext(model, typeof(Customer)));

            var customers = (new List<Customer>{
                new Customer { CustomerId = 1, Address = null },
                new Customer { CustomerId = 2, Address = new Address { City = "B" } },
                new Customer { CustomerId = 3, Address = new Address { City = "A" } }
            }).AsQueryable();
            ODataQuerySettings settings = new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.False };

            // Act & Assert
            Assert.Throws<NullReferenceException>(() => orderByOption.ApplyTo(customers, settings).ToArray());
        }
Beispiel #19
0
 /// <summary>
 /// Apply the $top query to the given IQueryable.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>.</param>
 /// <param name="querySettings">The query settings to use while applying this query option.</param>
 /// <returns>The new <see cref="IQueryable"/> after the top query has been applied to.</returns>
 public IOrderedQueryable <T> ApplyTo <T>(IQueryable <T> query, ODataQuerySettings querySettings)
 {
     return(ApplyToCore(query, querySettings) as IOrderedQueryable <T>);
 }
Beispiel #20
0
        /// <summary>
        /// Apply the apply query to the given IQueryable.
        /// </summary>
        /// <remarks>
        /// The <see cref="ODataQuerySettings.HandleNullPropagation"/> property specifies
        /// how this method should handle null propagation.
        /// </remarks>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <param name="querySettings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
        /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param>
        /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

            if (querySettings == null)
            {
                throw Error.ArgumentNull("querySettings");
            }

            if (assembliesResolver == null)
            {
                throw Error.ArgumentNull("assembliesResolver");
            }

            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            ApplyClause applyClause = ApplyClause;
            Contract.Assert(applyClause != null);

            // Ensure we have decided how to handle null propagation
            ODataQuerySettings updatedSettings = querySettings;
            if (querySettings.HandleNullPropagation == HandleNullPropagationOption.Default)
            {
                updatedSettings = new ODataQuerySettings(updatedSettings);
                updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query);
            }

            foreach (var transformation in applyClause.Transformations) 
            {
                if (transformation.Kind == TransformationNodeKind.Aggregate || transformation.Kind == TransformationNodeKind.GroupBy)
                {
                    var binder = new AggregationBinder(updatedSettings, assembliesResolver, ResultClrType, Context.Model, transformation as TransformationNode);
                    query = binder.Bind(query);
                    this.ResultClrType = binder.ResultClrType;
                }
                else if (transformation.Kind == TransformationNodeKind.Filter)
                {
                    var filterTransformation = transformation as FilterTransformationNode;
                    Expression filter = FilterBinder.Bind(filterTransformation.FilterClause, ResultClrType, Context.Model, assembliesResolver, updatedSettings);
                    query = ExpressionHelpers.Where(query, filter, ResultClrType);
                }
            }

            return query;
        }
Beispiel #21
0
 /// <summary>
 /// Apply the $top query to the given IQueryable.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>.</param>
 /// <param name="querySettings">The query settings to use while applying this query option.</param>
 /// <returns>The new <see cref="IQueryable"/> after the top query has been applied to.</returns>
 public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     return(ApplyToCore(query, querySettings));
 }
        public void ApplyTo_Adds_Missing_Keys_To_OrderBy(string oDataQuery, bool ensureStableOrdering, string expectedExpression)
        {
            // Arrange
            var model = new ODataModelBuilder()
                .Add_Customers_With_Keys_EntitySet(c => new { c.CustomerId, c.Name }).GetEdmModel();

            var message = new HttpRequestMessage(
                HttpMethod.Get,
                new Uri("http://server/service/Customers?" + oDataQuery)
            );

            var queryOptions = new ODataQueryOptions(new ODataQueryContext(model, typeof(Customer)), message);
            ODataQuerySettings querySettings = new ODataQuerySettings
            {
                EnsureStableOrdering = ensureStableOrdering,
            };

            // Act
            IQueryable finalQuery = queryOptions.ApplyTo(new Customer[0].AsQueryable(), querySettings);

            // Assert
            string queryExpression = ExpressionStringBuilder.ToString(finalQuery.Expression);
            queryExpression = queryExpression.Substring(queryExpression.IndexOf("]") + 2);

            Assert.Equal(queryExpression, expectedExpression);
        }
Beispiel #23
0
 /// <summary>
 /// Apply the individual query to the given IQueryable in the right order.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>.</param>
 /// <param name="querySettings">The settings to use in query composition.</param>
 /// <param name="ignoreQueryOptions">The query parameters that are already applied in queries.</param>
 /// <returns>The new <see cref="IQueryable"/> after the query has been applied to.</returns>
 public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings,
                                   AllowedQueryOptions ignoreQueryOptions)
 {
     _ignoreQueryOptions = ignoreQueryOptions;
     return(ApplyTo(query, querySettings));
 }
        public void ApplyTo_Builds_Default_OrderBy_No_Keys(string oDataQuery, bool ensureStableOrdering, string expectedExpression)
        {
            var model = ODataModelBuilderMocks.GetModelBuilderMock<ODataModelBuilder>().Add_Customer_No_Keys_EntityType().Add_Customers_No_Keys_EntitySet().GetEdmModel();

            var message = new HttpRequestMessage(
                HttpMethod.Get,
                new Uri("http://server/service/Customers?" + oDataQuery)
            );

            var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(Customer)), message);
            ODataQuerySettings querySettings = new ODataQuerySettings
            {
                EnsureStableOrdering = ensureStableOrdering
            };
            IQueryable finalQuery = options.ApplyTo(new Customer[0].AsQueryable(), querySettings);

            string queryExpression = ExpressionStringBuilder.ToString(finalQuery.Expression);
            queryExpression = queryExpression.Substring(queryExpression.IndexOf("]") + 2);

            Assert.Equal(queryExpression, expectedExpression);
        }
Beispiel #25
0
        public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

            if (querySettings == null)
            {
                throw Error.ArgumentNull("querySettings");
            }

            IQueryable result = query;

            // First apply $apply
            // Section 3.15 of the spec http://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/cs01/odata-data-aggregation-ext-v4.0-cs01.html#_Toc378326311
            if (IsAvailableODataQueryOption(Apply, AllowedQueryOptions.Apply))
            {
                result = Apply.ApplyTo(result, querySettings, _assembliesResolver);
                Request.ODataProperties().ApplyClause = Apply.ApplyClause;
                this.Context.ElementClrType = Apply.ResultClrType;
            }

            // Construct the actual query and apply them in the following order: filter, orderby, skip, top
            if (IsAvailableODataQueryOption(Filter, AllowedQueryOptions.Filter))
            {
                result = Filter.ApplyTo(result, querySettings, _assembliesResolver);
            }

            if (IsAvailableODataQueryOption(Count, AllowedQueryOptions.Count))
            {
                if (Request.ODataProperties().TotalCountFunc == null)
                {
                    Func <long> countFunc = Count.GetEntityCountFunc(result);
                    if (countFunc != null)
                    {
                        Request.ODataProperties().TotalCountFunc = countFunc;
                    }
                }

                if (ODataCountMediaTypeMapping.IsCountRequest(Request))
                {
                    return(result);
                }
            }

            OrderByQueryOption orderBy = OrderBy;

            // $skip or $top require a stable sort for predictable results.
            // Result limits require a stable sort to be able to generate a next page link.
            // If either is present in the query and we have permission,
            // generate an $orderby that will produce a stable sort.
            if (querySettings.EnsureStableOrdering &&
                (IsAvailableODataQueryOption(Skip, AllowedQueryOptions.Skip) ||
                 IsAvailableODataQueryOption(Top, AllowedQueryOptions.Top) ||
                 querySettings.PageSize.HasValue))
            {
                // If there is no OrderBy present, we manufacture a default.
                // If an OrderBy is already present, we add any missing
                // properties necessary to make a stable sort.
                // Instead of failing early here if we cannot generate the OrderBy,
                // let the IQueryable backend fail (if it has to).
                orderBy = orderBy == null
                            ? GenerateDefaultOrderBy(Context)
                            : EnsureStableSortOrderBy(orderBy, Context);
            }

            if (IsAvailableODataQueryOption(orderBy, AllowedQueryOptions.OrderBy))
            {
                result = orderBy.ApplyTo(result, querySettings);
            }

            if (IsAvailableODataQueryOption(Skip, AllowedQueryOptions.Skip))
            {
                result = Skip.ApplyTo(result, querySettings);
            }

            if (IsAvailableODataQueryOption(Top, AllowedQueryOptions.Top))
            {
                result = Top.ApplyTo(result, querySettings);
            }

            AddAutoExpandProperties(querySettings);

            if (SelectExpand != null)
            {
                var tempResult = ApplySelectExpand(result, querySettings);
                if (tempResult != default(IQueryable))
                {
                    result = tempResult;
                }
            }

            if (querySettings.PageSize.HasValue)
            {
                bool resultsLimited;
                result = LimitResults(result, querySettings.PageSize.Value, out resultsLimited);
                if (resultsLimited && Request.RequestUri != null && Request.RequestUri.IsAbsoluteUri && Request.ODataProperties().NextLink == null)
                {
                    Uri nextPageLink = Request.GetNextPageLink(querySettings.PageSize.Value);
                    Request.ODataProperties().NextLink = nextPageLink;
                }
            }

            return(result);
        }
 public IQueryable ApplyTo(IQueryable queryable, ODataQuerySettings settings)
 {
     return ApplyTo(queryable, settings, _defaultAssembliesResolver);
 }
Beispiel #27
0
 /// <summary>
 /// Apply the individual query to the given IQueryable in the right order.
 /// </summary>
 /// <param name="entity">The original entity.</param>
 /// <param name="querySettings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
 /// <param name="ignoreQueryOptions">The query parameters that are already applied in queries.</param>
 /// <returns>The new entity after the $select and $expand query has been applied to.</returns>
 /// <remarks>Only $select and $expand query options can be applied on single entities. This method throws if the query contains any other
 /// query options.</remarks>
 public virtual object ApplyTo(object entity, ODataQuerySettings querySettings, AllowedQueryOptions ignoreQueryOptions)
 {
     _ignoreQueryOptions = ignoreQueryOptions;
     return(ApplyTo(entity, new ODataQuerySettings()));
 }
        /// <summary>
        /// Applies the $select and $expand query options to the given entity using the given <see cref="ODataQuerySettings"/>.
        /// </summary>
        /// <param name="entity">The original entity.</param>
        /// <param name="settings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
        /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param>
        /// <returns>The new entity after the $select and $expand query has been applied to.</returns>
        public object ApplyTo(object entity, ODataQuerySettings settings, IAssembliesResolver assembliesResolver)
        {
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            if (settings == null)
            {
                throw Error.ArgumentNull("settings");
            }
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            // Ensure we have decided how to handle null propagation
            ODataQuerySettings updatedSettings = settings;
            if (settings.HandleNullPropagation == HandleNullPropagationOption.Default)
            {
                updatedSettings = new ODataQuerySettings(updatedSettings);
                updatedSettings.HandleNullPropagation = HandleNullPropagationOption.True;
            }

            return SelectExpandBinder.Bind(entity, updatedSettings, assembliesResolver, this);
        }
 public IQueryable ApplyTo(IQueryable queryable, ODataQuerySettings settings)
 {
     return(ApplyTo(queryable, settings, _defaultAssembliesResolver));
 }
 /// <summary>
 /// Enables a controller action to support OData query parameters.
 /// </summary>
 public EnableQueryAttribute()
 {
     _validationSettings = new ODataValidationSettings();
     _querySettings = new ODataQuerySettings();
 }
 /// <summary>
 /// Applies the $select and $expand query options to the given entity using the given <see cref="ODataQuerySettings"/>.
 /// </summary>
 /// <param name="entity">The original entity.</param>
 /// <param name="settings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param>
 /// <returns>The new entity after the $select and $expand query has been applied to.</returns>
 public object ApplyTo(object entity, ODataQuerySettings settings)
 {
     return(ApplyTo(entity, settings, _defaultAssembliesResolver));
 }