public ODataQuerySettings GetODataQuerySettings() {
   var settings = new ODataQuerySettings() {
     EnableConstantParameterization = this.EnableConstantParameterization,
     EnsureStableOrdering = this.EnsureStableOrdering,
     HandleNullPropagation = this.HandleNullPropagation,
     PageSize = this.PageSize > 0 ? this.PageSize : (int?)null
   };
   return settings;
 }
        public void Ctor_Initializes_All_Properties()
        {
            // Arrange & Act
            ODataQuerySettings querySettings = new ODataQuerySettings();

            // Assert
            Assert.Equal(HandleNullPropagationOption.Default, querySettings.HandleNullPropagation);
            Assert.True(querySettings.EnsureStableOrdering);
        }
        public PageResult<Order> GetOrders(ODataQueryOptions<Order> options)
        {
            var settings = new ODataQuerySettings();

            var fromDatabase = _context.Orders.Where(order => order.Freight != 123);

            var results = options.ApplyTo(fromDatabase.AsQueryable(), settings);

            return new PageResult<Order>(
                results as IQueryable<Order>,
                Request.ODataProperties().NextLink,
                Request.ODataProperties().TotalCount);
        }
        public void GetResultSize_ReturnsEffectivePageSize(string top, int? pageSize, int expected)
        {
            // Arrange
            ODataQueryContext context = new ODataQueryContext(EdmModelMock.Create<Movie>("Movies"), typeof(Movie));
            Uri address = new Uri("http://localhost?{0}".FormatInvariant(top));
            ODataQueryOptions query = new ODataQueryOptions(context, new HttpRequestMessage { RequestUri = address });
            ODataQuerySettings settings = new ODataQuerySettings() { PageSize = pageSize };

            // Act
            int actual = TableUtils.GetResultSize(query, settings);

            // Assert
            Assert.Equal(expected, actual);
        }
        public PageResult<ArticleDto> Get(ODataQueryOptions<ArticleDto> options)
        {
            var settings = new ODataQuerySettings { PageSize = 10, EnsureStableOrdering = false };

            var artikelQuery = productsContext.Articles
                .OrderBy(a => a.Id).AsNoTracking().Project().To<ArticleDto>(null,
                dest => dest.Id, dest => dest.Name, dest => dest.Code);
            var results = options.ApplyTo(artikelQuery, settings);

            return new PageResult<ArticleDto>(
                    results as IEnumerable<ArticleDto>,
                    Request.ODataProperties().NextLink,
                    Request.ODataProperties().TotalCount);
        }
예제 #6
0
        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)), null);

            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());
        }
 internal static int GetCount(ODataQueryOptions<VELEMIMUNKAINMLIST> queryOptions)
 {
     using (MIRTUSZContext.MIRTUSZDataContext mirtuszDC = new MIRTUSZContext.MIRTUSZDataContext())
     {
         mirtuszDC.Connection.Open();
         if (queryOptions.Filter != null)
         {
             ODataQuerySettings settings = new ODataQuerySettings()
             {
                 PageSize = 1000000
             };
             IQueryable query = queryOptions.ApplyTo(mirtuszDC.VELEMIMUNKAINMLISTs, settings);
             return query.Cast<VELEMIMUNKAINMLIST>().Count();
         }
         return mirtuszDC.VELEMIMUNKAINMLISTs.Count();
     }
 }
예제 #8
0
        public PageResult<ViewTradeResource> Get([FromUri] FilterOptions filterOptions, ODataQueryOptions queryOptions)
        {
            var querySettings = new ODataQuerySettings { PageSize = 20 };

            var data =
                _tradeRepository
                .Get(filterOptions.BasketName);

            var results = queryOptions.ApplyTo(_mappingEngine.Map<IEnumerable<Trade>, IEnumerable<ViewTradeResource>>(data).AsQueryable(), querySettings)
                .Cast<ViewTradeResource>();

            return new PageResult<ViewTradeResource>(
                    results,
                    Request.GetNextPageLink(),
                    Request.GetInlineCount()
                );
        }
예제 #9
0
        public PageResult<Customer> Get(ODataQueryOptions<Customer> options)
        {
            Guid VALID_TENANT_ID = Guid.Parse("7b6791d5-8658-44e5-86bc-8181735d0bf7");

            IQueryable query = dbContext.Customers.Where(c => c.Tenant_Id == VALID_TENANT_ID);

            ODataQuerySettings odataSettings = new ODataQuerySettings();

            if (options.Filter != null)
            {
                // set validator that restricts client's filtering
                options.Filter.Validator = new QuoteQueryValidator();
                options.Validate(new ODataValidationSettings());

                query = options.Filter.ApplyTo(query, odataSettings);
            }

            // get the total count
            IQueryable<Customer> custQuery = query as IQueryable<Customer>;
            long totalCount = custQuery.LongCount();

            if (options.OrderBy != null)
            {
                query = options.OrderBy.ApplyTo(query, odataSettings);
            }

            if (options.Skip != null)
                query = options.Skip.ApplyTo(query, odataSettings);

            if (options.Top != null)
                query = options.Top.ApplyTo(query, odataSettings);

               // if (options.SelectExpand != null)
             //   query = options.SelectExpand.ApplyTo(query, odataSettings);

            //var resultList = new List<Customer>(query);

            var retValue = new PageResult<Customer>(
                    query as IEnumerable<Customer>,
                    Request.GetNextPageLink(),
                    totalCount);

            return retValue;
        }
예제 #10
0
        public PageResult<Vessel> Get(ODataQueryOptions<Vessel> options)
        {
            // Implementation from here:
            // http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options

            // TODO May want to limit additional query options
            ODataQuerySettings settings = new ODataQuerySettings()
            {
                PageSize = 15
            };

            var repo = TubsDataService.GetRepository<Vessel>(MvcApplication.CurrentSession);
            IQueryable results = options.ApplyTo(repo.All(), settings);

            // Not sure how to get the appropriate count
            // what is wanted is repo.All().Where(???).Count();
            return new PageResult<Vessel>(
                results as IEnumerable<Vessel>,
                Request.GetNextPageLink(),
                Request.GetInlineCount()
            );
        }
예제 #11
0
        public PageResult<BasketResource> Get([FromUri]FilterOptions options, ODataQueryOptions queryOptions)
        {
            var querySettings = new ODataQuerySettings { PageSize = 20 };

            var data = _basketRepository
                .Get(options.QuoteId,
                    options.BrokerName,
                    options.CustomerName,
                    options.BasketName)
                .Project()
                .To<BasketResource>()
                .Take(500);

            //return data;
            var results = queryOptions.ApplyTo(data, querySettings)
                .Cast<BasketResource>();

            return new PageResult<BasketResource>(
                    results,
                    Request.GetNextPageLink(),
                    Request.GetInlineCount()
                );
        }
예제 #12
0
        public PageResult<BrokerResource> Get([FromUri]FilterOptions options, ODataQueryOptions queryOptions)
        {
            var querySettings = new ODataQuerySettings {PageSize = 20};

            var data = _brokerRepository
                .Get(options.QuoteId,
                    options.BrokerName,
                    null, //new long[] { 1234, 4321 },
                    options.BasketName)
                .Project()
                .To<BrokerResource>()
                .Where(b => !options.Active.HasValue || b.Active == options.Active.Value)
                .Take(500);

            //return data;
            var results = queryOptions.ApplyTo(data, querySettings)
                .Cast<BrokerResource>();

            return new PageResult<BrokerResource>(
                    results,
                    Request.GetNextPageLink(),
                    Request.GetInlineCount()
                );
        }
예제 #13
0
        public PageResult<CustomerResource> Get([FromUri]FilterOptions options, ODataQueryOptions queryOptions)
        {
            var querySettings = new ODataQuerySettings { PageSize = 20 };

            //var svc = new PcdsServiceClient();
            //var data = svc.GetGroupDetails(options.CustomerName)
            var data = GetCustomers()
                .Where(c => (options.CustomerName == null) || (options.CustomerName != null) && c.CustomerName.Contains(options.CustomerName))
                //.Select(d => new CustomerResource { CustomerName = d.Details.GROUP_NAME, NumberOfSites = d.SiteCount, Id = (int)d.Details.ID, CustomerId = "C" + d.Details.ID.ToString()})
                .AsQueryable()
                .Take(500);
                //.Project()
                //.To<CustomerResource>();

            //return data;
            var results = queryOptions.ApplyTo(data, querySettings)
                .Cast<CustomerResource>();

            return new PageResult<CustomerResource>(
                    results,
                    Request.GetNextPageLink(),
                    Request.GetInlineCount()
                );
        }
        public IQueryable ApplyTo(IQueryable queryable, ODataQuerySettings settings)
        {
            if (queryable == null)
            {
                throw Error.ArgumentNull("queryable");
            }
            if (settings == null)
            {
                throw Error.ArgumentNull("settings");
            }

            // 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);
        }
        /// <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)
        {
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            if (settings == null)
            {
                throw Error.ArgumentNull("settings");
            }

            // 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, this);
        }
        /// <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 IQueryable that we are applying filter query against.</param>
        /// <param name="querySettings">Specifies if we need to handle null propagation. Pass false if the underlying query provider handles null propagation. Otherwise pass true.</param>
        /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param>
        /// <returns>The query that 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");
            }

            FilterQueryNode node = QueryNode;
            Contract.Assert(node != null);

            Expression filter = FilterBinder.Bind(node, Context.EntityClrType, Context.Model, assembliesResolver, querySettings);
            query = ExpressionHelpers.Where(query, filter, Context.EntityClrType);
            return query;
        }
        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), "Customers"), message);
            ODataQuerySettings querySettings = new ODataQuerySettings 
            { 
                EnsureStableOrdering = ensureStableOrdering,
            };

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

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

            Assert.Equal(queryExpression, expectedExpression);
        }
 public QueryableAttribute(bool handleNullPropagation = false)
 {
     this.querySettings = new ODataQuerySettings();
 }
        /// <summary>
        /// Apply the individual query to the given IQueryable in the right order.
        /// </summary>
        /// <param name="query">The IQueryable that we are applying query against.</param>
        /// <param name="querySettings">The settings to use in query composition.</param>
        /// <returns>The query that the query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

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

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

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

            OrderByQueryOption orderBy = OrderBy;

            // $skip or $top require a stable sort for predictable results.
            // If either is present in the query and we have permission,
            // generate an $orderby that will produce a stable sort.
            if ((Skip != null || Top != null) && querySettings.EnsureStableOrdering && !Context.IsPrimitiveClrType)
            {
                // 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);
            }

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

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

            return result;
        }
        // demo 2: low level APIs
        public IQueryable<QueryCompositionCustomer> Get(ODataQueryOptions queryOptions)
        {
            if (!ModelState.IsValid)
            {
                throw new HttpResponseException(HttpStatusCode.BadRequest);
            }

            IQueryable<QueryCompositionCustomer> result = null;
            try
            {
                ODataQuerySettings querySettings = new ODataQuerySettings 
                { 
                    EnsureStableOrdering = false
                };
                result = queryOptions.ApplyTo(QueryCompositionCustomerController.CustomerList.AsQueryable(), querySettings) as IQueryable<QueryCompositionCustomer>;
            }
            catch (ODataException exception)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, exception));
            }

            return result;
        }
        public void ApplyTo_Builds_Default_OrderBy_No_Keys(string oDataQuery, bool ensureStableOrdering, string expectedExpression)
        {
            var model = new 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), "Customers"), message);
            ODataQuerySettings querySettings = new ODataQuerySettings 
            { 
                EnsureStableOrdering = ensureStableOrdering 
            };
            IQueryable finalQuery = options.ApplyTo(new Customer[0].AsQueryable(), querySettings);

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

            Assert.Equal(queryExpression, expectedExpression);
        }
예제 #22
0
        public static Uri GetNextLink(Uri currentRequestUri, long? totalResultCount, object queryParameters, ODataQueryOptions options, ODataQuerySettings settings)
        {
            if (!totalResultCount.HasValue || totalResultCount.Value <= MaxPageSize || totalResultCount.Value == 0)
            {
                return null; // no need for a next link if there are no additional results on this page
            }
           
            var skipCount = (options.Skip != null ? options.Skip.Value : 0) + Math.Min(totalResultCount.Value, (settings.PageSize != null ? settings.PageSize.Value : SearchAdaptor.MaxPageSize));

            if (totalResultCount.Value <= skipCount)
            {
                return null; // no need for a next link if there are no additional results in the result set
            }

            var queryBuilder = new StringBuilder();
            
            var queryParametersCollection = new RouteValueDictionary(queryParameters);
            foreach (var queryParameter in queryParametersCollection)
            {
                queryBuilder.Append(Uri.EscapeDataString(queryParameter.Key));
                queryBuilder.Append("=");
                if (queryParameter.Value != null)
                {
                    if (queryParameter.Value is string)
                    {
                        queryBuilder.Append(Uri.EscapeDataString("'" + queryParameter.Value + "'"));
                    }
                    else if (queryParameter.Value is bool)
                    {
                        queryBuilder.Append(queryParameter.Value.ToString().ToLowerInvariant());
                    }
                    else
                    {
                        queryBuilder.Append(queryParameter.Value.ToString().ToLowerInvariant());
                    }
                }
                queryBuilder.Append("&");
            }

            if (options.SelectExpand != null)
            {
                if (!string.IsNullOrEmpty(options.SelectExpand.RawSelect))
                {
                    queryBuilder.Append("$select=");
                    queryBuilder.Append(options.SelectExpand.RawSelect);
                    queryBuilder.Append("&");
                }
                if (!string.IsNullOrEmpty(options.SelectExpand.RawExpand))
                {
                    queryBuilder.Append("$expand=");
                    queryBuilder.Append(options.SelectExpand.RawExpand);
                    queryBuilder.Append("&");
                }
            }

            if (options.Filter != null)
            {
                queryBuilder.Append("$filter=");
                queryBuilder.Append(options.Filter.RawValue);
                queryBuilder.Append("&");
            }

            if (options.OrderBy != null)
            {
                queryBuilder.Append("$orderby=");
                queryBuilder.Append(options.OrderBy.RawValue);
                queryBuilder.Append("&");
            }

            if (skipCount > 0)
            {
                queryBuilder.Append("$skip=");
                queryBuilder.Append(skipCount);
                queryBuilder.Append("&");
            }

            if (options.Top != null)
            {
                queryBuilder.Append("$top=");
                queryBuilder.Append(options.Top.RawValue);
                queryBuilder.Append("&");
            }

            var queryString = queryBuilder.ToString().TrimEnd('&');

            var builder = new UriBuilder(currentRequestUri);
            builder.Query = queryString;
            return builder.Uri;
        }
예제 #23
0
 private IQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
 {
     return(ExpressionHelpers.Take(query, Value, Context.ElementClrType, querySettings.EnableConstantParameterization));
 }
예제 #24
0
 /// <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>
 /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns>
 public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     return(ApplyTo(query, querySettings, _defaultAssembliesResolver));
 }
예제 #25
0
        /// <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;
        }
예제 #26
0
        public PageResult<Product> GetProducts(ODataQueryOptions<Product> options)
        {
            var settings = new ODataQuerySettings()
            {
                PageSize = 1
            };

            if (options.OrderBy != null)
            {
                options.OrderBy.Validator = new MyOrderByValidator();
            }

            var settingsVal = new ODataValidationSettings()
            {
                // Initialize settings as needed.
                AllowedFunctions = AllowedFunctions.AllMathFunctions
            };
            // Validate
            options.Validate(settingsVal);

            IQueryable results = options.ApplyTo(Repository.GetAll().Select(AsProductTo), settings);

            return new PageResult<Product>(
                results as IEnumerable<Product>,
                Request.GetNextPageLink(),
                Request.GetInlineCount());
        }
예제 #27
0
 /// <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>
 /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns>
 public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     return ApplyTo(query, querySettings, _defaultAssembliesResolver);
 }
예제 #28
0
 /// <summary>
 /// Apply the $orderby query to the given IQueryable.
 /// </summary>
 /// <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>
 /// <returns>The new <see cref="IQueryable"/> after the orderby query has been applied to.</returns>
 public IOrderedQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     return(ApplyToCore(query, querySettings));
 }
예제 #29
0
        /// <summary>
        /// Apply the individual query to the given IQueryable in the right order.
        /// </summary>
        /// <param name="query">The IQueryable that we are applying query against.</param>
        /// <param name="querySettings">The settings to use in query composition.</param>
        /// <returns>The query that 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");
            }

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

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

            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 && !Context.IsPrimitiveClrType &&
                (Skip != null || Top != null || querySettings.ResultLimit.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);
            }

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

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

            if (querySettings.ResultLimit.HasValue)
            {
                bool resultsLimited;
                result = LimitResults(result, querySettings.ResultLimit.Value, Context, out resultsLimited);
                if (resultsLimited && Request.RequestUri != null && Request.RequestUri.IsAbsoluteUri)
                {
                    Uri nextPageLink = GetNextPageLink(Request, querySettings.ResultLimit.Value);
                    Request.Properties.Add(NextPageLinkPropertyKey, nextPageLink);
                }
            }

            return(result);
        }
예제 #30
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, 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);
        }
        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);
        }
예제 #32
0
        private IQueryable ExecuteQuery(IEnumerable query, HttpRequestMessage request, HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
        {
            Type originalQueryType = query.GetType();
            Type entityClrType = TypeHelper.GetImplementedIEnumerableType(originalQueryType);

            if (entityClrType == null)
            {
                // The element type cannot be determined because the type of the content
                // is not IEnumerable<T> or IQueryable<T>.
                throw Error.InvalidOperation(
                    SRResources.FailedToRetrieveTypeToBuildEdmModel,
                    this.GetType().Name,
                    actionDescriptor.ActionName,
                    actionDescriptor.ControllerDescriptor.ControllerName,
                    originalQueryType.FullName);
            }

            ODataQueryContext queryContext = CreateQueryContext(entityClrType, configuration, actionDescriptor);
            ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, request);
            ValidateQuery(request, queryOptions);

            // apply the query
            IQueryable queryable = query as IQueryable;
            if (queryable == null)
            {
                queryable = query.AsQueryable();
            }

            ODataQuerySettings querySettings = new ODataQuerySettings
            {
                EnsureStableOrdering = EnsureStableOrdering,
                HandleNullPropagation = HandleNullPropagation,
                MaxAnyAllExpressionDepth = MaxAnyAllExpressionDepth,
                ResultLimit = _resultLimit
            };

            return queryOptions.ApplyTo(queryable, querySettings);
        }
 /// <summary>
 /// Enables a controller action to support OData query parameters.
 /// </summary>
 public QueryableAttribute()
 {
     _validationSettings = new ODataValidationSettings();
     _querySettings = new ODataQuerySettings();
 }
예제 #34
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 (InlineCount != null && Request.GetInlineCount() == null)
            {
                long?count = InlineCount.GetEntityCount(result);
                if (count.HasValue)
                {
                    Request.SetInlineCount(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 (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);
            }

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

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

            if (SelectExpand != null)
            {
                Request.SetSelectExpandClause(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.GetNextPageLink() == null)
                {
                    Uri nextPageLink = GetNextPageLink(Request, querySettings.PageSize.Value);
                    Request.SetNextPageLink(nextPageLink);
                }
            }

            return(result);
        }
        public void ApplyTo_Does_Not_Replace_Original_OrderBy_With_Missing_Keys()
        {
            // Arrange
            var model = new 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), "Customers"), message);
            OrderByQueryOption originalOption = queryOptions.OrderBy;
            ODataQuerySettings querySettings = new ODataQuerySettings();

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

            // Assert
            Assert.ReferenceEquals(originalOption, queryOptions.OrderBy);
        }
예제 #36
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 override IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
 {
     ValidateQuery(query);
     return(base.ApplyTo(query, querySettings));
 }
예제 #37
0
 public NHQueryHelper(ODataQuerySettings querySettings)
     : base(querySettings)
 {
 }
예제 #38
0
 /// <summary>
 /// Apply the $orderby query to the given IQueryable.
 /// </summary>
 /// <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>
 /// <returns>The new <see cref="IQueryable"/> after the orderby query has been applied to.</returns>
 public IOrderedQueryable <T> ApplyTo <T>(IQueryable <T> query, ODataQuerySettings querySettings)
 {
     return(ApplyToCore(query, querySettings) as IOrderedQueryable <T>);
 }