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