Exemplo n.º 1
0
 /// <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;
 }
Exemplo n.º 2
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;
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

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

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

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

            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))
            {
                query = orderBy.ApplyTo(query, querySettings);
            }
            if (IsAvailableODataQueryOption(Skip, AllowedQueryOptions.Skip))
            {
                query = Skip.ApplyTo(query, querySettings);
            }
            if (IsAvailableODataQueryOption(Top, AllowedQueryOptions.Top))
            {
                query = Top.ApplyTo(query, querySettings);
            }

            AddAutoExpandProperties(querySettings);

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

            if (querySettings.PageSize.HasValue)
            {
                bool resultsLimited = true;
                query = LimitResults(query, querySettings.PageSize.Value, out resultsLimited);
                var uriString = Request.GetDisplayUrl();
                if (!string.IsNullOrWhiteSpace(uriString))
                {
                    var uri = new Uri(uriString);
                    if (resultsLimited && uri != null && uri.IsAbsoluteUri && Request.ODataProperties().NextLink == null)
                    {
                        Uri nextPageLink = Request.GetNextPageLink(querySettings.PageSize.Value);
                        Request.ODataProperties().NextLink = nextPageLink;
                    }
                }
            }

            return(query);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Apply the $skiptoken query to the given IQueryable.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>.</param>
 /// <param name="skipTokenQueryOption">The query option that contains all the relevant information for applying skiptoken.</param>
 /// <param name="querySettings">The query settings to use while applying this query option.</param>
 /// <param name="queryOptions">Information about the other query options.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public abstract IQueryable ApplyTo(IQueryable query, SkipTokenQueryOption skipTokenQueryOption,
                                    ODataQuerySettings querySettings, ODataQueryOptions queryOptions);
Exemplo n.º 4
0
 /// <summary>
 /// Apply the $skiptoken query to the given IQueryable.
 /// </summary>
 /// <param name="query">The original <see cref="IQueryable"/>, not null.</param>
 /// <param name="skipTokenQueryOption">The skiptoken query option which needs to be applied to this query option, not null.</param>
 /// <param name="querySettings">The query settings to use while applying this query option, not null.</param>
 /// <param name="queryOptions">Information about the other query options, could be null.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public override IQueryable ApplyTo(IQueryable query, SkipTokenQueryOption skipTokenQueryOption,
                                    ODataQuerySettings querySettings, ODataQueryOptions queryOptions)
 {
     return(ApplyToImplementation(query, skipTokenQueryOption, querySettings, queryOptions));
 }
        public static ODataQuerySettings UpdateQuerySettings(this ODataQueryContext context, ODataQuerySettings querySettings, IQueryable query)
        {
            ODataQuerySettings updatedSettings = (context == null || context.RequestContainer == null)
                ? new ODataQuerySettings()
                : context.RequestContainer.GetRequiredService <ODataQuerySettings>();

            updatedSettings.CopyFrom(querySettings);

            if (updatedSettings.HandleNullPropagation == HandleNullPropagationOption.Default)
            {
                updatedSettings.HandleNullPropagation = query != null
                    ? HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query)
                    : HandleNullPropagationOption.True;
            }

            return(updatedSettings);
        }
Exemplo n.º 6
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 <object> propertiesSoFar     = new HashSet <object>();
            HashSet <string> openPropertiesSoFar = new HashSet <string>();
            bool             orderByItSeen       = false;

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

                if (propertyNode != null)
                {
                    // Use autonomy class to achieve value equality for HasSet.
                    var edmPropertyWithPath    = new { propertyNode.Property, propertyNode.PropertyPath };
                    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(edmPropertyWithPath))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, edmPropertyWithPath.PropertyPath));
                    }

                    propertiesSoFar.Add(edmPropertyWithPath);

                    if (propertyNode.OrderByClause != null)
                    {
                        querySoFar = AddOrderByQueryForProperty(query, querySettings, propertyNode.OrderByClause, querySoFar, direction, alreadyOrdered);
                    }
                    else
                    {
                        querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, edmPropertyWithPath.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 (openPropertiesSoFar.Contains(openPropertyNode.PropertyName))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, openPropertyNode.PropertyPath));
                    }

                    openPropertiesSoFar.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);
        }
Exemplo n.º 7
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>);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Apply the $skiptoken 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>
 /// <param name="queryOptions">Information about the other query options.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public virtual IQueryable <T> ApplyTo <T>(IQueryable <T> query, ODataQuerySettings querySettings, ODataQueryOptions queryOptions)
 {
     QuerySettings = querySettings;
     QueryOptions  = queryOptions;
     return(skipTokenHandler.ApplyTo <T>(query, this) as IOrderedQueryable <T>);
 }
Exemplo n.º 9
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(nameof(query));
            }

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

            IQueryable    result       = query;
            IODataFeature odataFeature = Request.ODataFeature();

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

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

                if (Request.IsCountRequest())
                {
                    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 = GenerateStableOrder();
            }

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

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

            AddAutoSelectExpandProperties();

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

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

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

            result = ApplyPaging(result, querySettings);

            return(result);
        }
Exemplo n.º 10
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));
 }
Exemplo n.º 11
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 assembly 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, AssembliesResolver assembliesResolver)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

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

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

            var filter = FilterBinder.Bind(FilterClause, Context.ElementClrType, Context.Model, assembliesResolver, querySettings);
            return ExpressionHelpers.Where(query, filter, Context.ElementClrType);
        }
Exemplo n.º 12
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>
        /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings)
        {
            if (query == null)
            {
                throw Error.ArgumentNull(nameof(query));
            }

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

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

            // Linq to SQL not supported for $apply
            if (query.Provider.GetType().Namespace == HandleNullPropagationOptionHelper.Linq2SqlQueryProviderNamespace)
            {
                throw Error.NotSupported(SRResources.ApplyQueryOptionNotSupportedForLinq2SQL);
            }

            ApplyClause applyClause = ApplyClause;

            Contract.Assert(applyClause != null);

            ODataQuerySettings updatedSettings = Context.UpdateQuerySettings(querySettings, query);

            // The IWebApiAssembliesResolver service is internal and can only be injected by WebApi.
            // This code path may be used in cases when the service container is not available
            // and the service container is available but may not contain an instance of IWebApiAssembliesResolver.
            IAssemblyResolver assembliesResolver = AssemblyResolverHelper.Default;

            if (Context.RequestContainer != null)
            {
                IAssemblyResolver injectedResolver = Context.RequestContainer.GetService <IAssemblyResolver>();
                if (injectedResolver != null)
                {
                    assembliesResolver = injectedResolver;
                }
            }

            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);
                    query = binder.Bind(query);
                    this.ResultClrType = binder.ResultClrType;
                }
                else if (transformation.Kind == TransformationNodeKind.Compute)
                {
                    var binder = new ComputeBinder(updatedSettings, assembliesResolver, ResultClrType, Context.Model, (ComputeTransformationNode)transformation);
                    query = binder.Bind(query);
                    this.ResultClrType = binder.ResultClrType;
                }
                else if (transformation.Kind == TransformationNodeKind.Filter)
                {
                    var        filterTransformation = transformation as FilterTransformationNode;
                    Expression filter = FilterBinder.Bind(query, filterTransformation.FilterClause, ResultClrType, Context, querySettings);
                    query = ExpressionHelpers.Where(query, filter, ResultClrType);
                }
            }

            return(query);
        }
Exemplo n.º 13
0
 /// <summary>
 /// Apply the $skiptoken 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>
 /// <param name="queryOptions">Information about the other query options.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, ODataQueryOptions queryOptions)
 {
     return(Handler.ApplyTo(query, this, querySettings, queryOptions));
 }
Exemplo n.º 14
0
 /// <summary>
 /// Apply the $skiptoken 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>
 /// <param name="queryOptions">Information about the other query options.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public virtual IQueryable <T> ApplyTo <T>(IQueryable <T> query, ODataQuerySettings querySettings, ODataQueryOptions queryOptions)
 {
     return(Handler.ApplyTo(query, this, querySettings, queryOptions) as IOrderedQueryable <T>);
 }
        /// <summary>
        /// Core logic for applying the query option to the IQueryable.
        /// </summary>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <param name="querySettings">Query setting used for validating the query option.</param>
        /// <param name="orderByNodes">OrderBy information required to correctly apply the query option for default implementation.</param>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
        /// <param name="skipTokenRawValue">The raw string value of the skiptoken query parameter.</param>
        /// <returns></returns>
        private static IQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings, IList <OrderByNode> orderByNodes, ODataQueryContext context, string skipTokenRawValue)
        {
            if (query == null)
            {
                throw Error.ArgumentNull(nameof(query));
            }

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

            IDictionary <string, OrderByDirection> directionMap;

            if (orderByNodes != null)
            {
                directionMap =
                    orderByNodes.OfType <OrderByPropertyNode>().ToDictionary(node => node.Property.Name, node => node.Direction);
            }
            else
            {
                directionMap = new Dictionary <string, OrderByDirection>();
            }

            IDictionary <string, object> propertyValuePairs = PopulatePropertyValuePairs(skipTokenRawValue, context);

            if (propertyValuePairs.Count == 0)
            {
                throw Error.InvalidOperation("Unable to get property values from the skiptoken value.");
            }

            ExpressionBinderBase binder = context.GetFilterBinder(querySettings);
            bool parameterizeConstant   = querySettings.EnableConstantParameterization;
            ParameterExpression param   = Expression.Parameter(context.ElementClrType);

            Expression where = null;

            /* We will create a where lambda of the following form -
             * Where (Prop1>Value1)
             * OR (Prop1=Value1 AND Prop2>Value2)
             * OR (Prop1=Value1 AND Prop2=Value2 AND Prop3>Value3)
             * and so on...
             * Adding the first true to simplify implementation.
             */
            Expression lastEquality  = null;
            bool       firstProperty = true;

            foreach (KeyValuePair <string, object> item in propertyValuePairs)
            {
                string           key      = item.Key;
                MemberExpression property = Expression.Property(param, key);
                object           value    = item.Value;

                Expression     compare   = null;
                ODataEnumValue enumValue = value as ODataEnumValue;
                if (enumValue != null)
                {
                    value = enumValue.Value;
                }

                Expression constant = parameterizeConstant ? LinqParameterContainer.Parameterize(value.GetType(), value) : Expression.Constant(value);
                if (directionMap.ContainsKey(key) && directionMap[key] == OrderByDirection.Descending)
                {
                    compare = binder.CreateBinaryExpression(BinaryOperatorKind.LessThan, property, constant, true);
                }
                else
                {
                    compare = binder.CreateBinaryExpression(BinaryOperatorKind.GreaterThan, property, constant, true);
                }

                if (firstProperty)
                {
                    lastEquality  = binder.CreateBinaryExpression(BinaryOperatorKind.Equal, property, constant, true);
                    where         = compare;
                    firstProperty = false;
                }
                else
                {
                    Expression condition = Expression.AndAlso(lastEquality, compare);
                    where        = Expression.OrElse(where, condition);
                    lastEquality = Expression.AndAlso(lastEquality, binder.CreateBinaryExpression(BinaryOperatorKind.Equal, property, constant, true));
                }
            }

            Expression whereLambda = Expression.Lambda(where, param);

            return(ExpressionHelpers.Where(query, whereLambda, query.ElementType));
        }
Exemplo n.º 16
0
 /// <summary>
 /// Apply the $skiptoken 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>
 /// <param name="queryOptions">Information about the other query options.</param>
 /// <returns>The new <see cref="IQueryable"/> after the skiptoken query has been applied to.</returns>
 public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, ODataQueryOptions queryOptions)
 {
     QuerySettings = querySettings;
     QueryOptions  = queryOptions;
     return(skipTokenHandler.ApplyTo(query, this));
 }
Exemplo n.º 17
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>
        /// 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="pageSize">The page size for this query</param>
        /// <param name="queryOptions"></param>
        /// <returns>The new <see cref="IQueryable"/> after the query has been applied to.</returns>
        public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, int?pageSize,
                                          ODataQueryOptions queryOptions)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

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

            var 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 && queryOptions.IgnoreSkip == false) ||
                 (Top != null && queryOptions.IgnoreTop == false) ||
                 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
                            ? OrderByHelper.GenerateDefaultOrderBy(Context, _serviceProvider)
                            : OrderByHelper.EnsureStableSortOrderBy(orderBy, Context, _serviceProvider);
            }

            // 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 (Apply != null)
            {
                query = Apply.ApplyTo(query, querySettings, _assemblyProvider);
                Request.ODataFeature().ApplyClause = Apply.ApplyClause;
                Context.ElementClrType = Apply.ResultClrType;
            }

            if (orderBy != null && Apply == null)
            {
                query = orderBy.ApplyTo(query, querySettings);
            }

            if (Skip.HasValue && queryOptions.IgnoreSkip == false)
            {
                query = ExpressionHelpers.Skip(query, Skip.Value, Context.ElementClrType, false);
            }

            int?take = null;

            if (querySettings.PageSize.HasValue)
            {
                take = Math.Min(querySettings.PageSize.Value, int.MaxValue);
            }
            if (Top.HasValue && queryOptions.IgnoreTop == false)
            {
                take = Math.Min(Top.Value, take ?? int.MaxValue);
            }
            if (take.HasValue)
            {
                query = ExpressionHelpers.Take(query, take.Value, Context.ElementClrType, false);
            }

            if (SelectExpand != null)
            {
                query = SelectExpand.ApplyTo(query, querySettings, _assemblyProvider);
            }

            if (CountQueryOption != null)
            {
                if (Request.ODataFeature().TotalCountFunc == null)
                {
                    Func <long> countFunc = CountQueryOption.GetEntityCountFunc(query);
                    if (countFunc != null)
                    {
                        Request.ODataFeature().TotalCountFunc = countFunc;
                    }
                }

                if (ODataCountMediaTypeMapping.IsCountRequest(Request.HttpContext))
                {
                    return(query);
                }
            }
            if (pageSize.HasValue && Apply == null)
            {
                bool resultsLimited;
                query = LimitResults(query, pageSize.Value, out resultsLimited);
                if (resultsLimited && Request.GetDisplayUrl() != null && new Uri(Request.GetDisplayUrl()).IsAbsoluteUri&& Request.ODataFeature().NextLink == null)
                {
                    Uri nextPageLink = Request.GetNextPageLink(pageSize.Value);
                    Request.ODataFeature().NextLink = nextPageLink;
                }
            }
            return(query);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Apply the $orderby query to the given IQueryable.
        /// </summary>
        /// <param name="query">The original <see cref="IQueryable"/>.</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 = Context.GetODataQuerySettings();

            return(ApplyToCore(query, querySettings) as IOrderedQueryable <T>);
        }
Exemplo n.º 20
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));
 }
Exemplo n.º 21
0
        /// <summary>
        /// Apply the $orderby query to the given IQueryable.
        /// </summary>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <returns>The new <see cref="IQueryable"/> after the orderby query has been applied to.</returns>
        public IOrderedQueryable ApplyTo(IQueryable query)
        {
            ODataQuerySettings querySettings = Context.GetODataQuerySettings();

            return(ApplyToCore(query, querySettings));
        }
 /// <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));
 }
 public IQueryable ApplyTo(IQueryable queryable, ODataQuerySettings settings)
 {
     return(ApplyTo(queryable, settings, _assemblyProvider));
 }
 /// <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, _assemblyProvider));
 }
Exemplo n.º 25
0
        ///// <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, string AssembliesResolver)
        //{
        //    return ApplyTo(entity, settings, AssembliesResolver);
        //}
        /// <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 name of the assembly 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, AssembliesResolver 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);
        }