Ejemplo n.º 1
0
        /// <summary>Filters a query like a SQL WHERE clause does.</summary>
        /// <param name="service">Service with data and configuration.</param>
        /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param>
        /// <param name="source">Original source for query expression.</param>
        /// <returns>The composed query expression.</returns>
        internal static Expression Where(IDataService service, RequestDescription requestDescription, Expression source)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(source != null, "source != null");
            Debug.Assert(requestDescription != null, "requestDescription != null");

            FilterClause filterClause = new RequestExpressionParser(service, requestDescription).ParseFilter();

            if (filterClause == null)
            {
                return(source);
            }

            bool filterQueryApplicable = requestDescription.TargetKind == RequestTargetKind.Resource ||
                                         requestDescription.TargetKind == RequestTargetKind.OpenProperty ||
                                         requestDescription.TargetKind == RequestTargetKind.ComplexObject ||
                                         requestDescription.CountOption == RequestQueryCountOption.CountSegment;

            if (!filterQueryApplicable)
            {
                throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryFilterOptionNotApplicable);
            }

            Type queryElementType = source.ElementType();

            Debug.Assert(queryElementType != null, "queryElementType != null");

            ParameterExpression parameterForIt = Expression.Parameter(queryElementType, "it");

            Debug.Assert(
                (requestDescription.TargetResourceSet == null && (requestDescription.TargetResourceType == null || requestDescription.TargetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)) ||
                (requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.ResourceTypeKind == ResourceTypeKind.EntityType),
                "setForIt cannot be null if typeForIt is an entity type.");
            Debug.Assert(
                requestDescription.TargetResourceType == null && parameterForIt.Type == typeof(object) ||
                requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.InstanceType == parameterForIt.Type,
                "non-open type expressions should have a typeForIt");

            var translator          = NodeToExpressionTranslator.Create(service, requestDescription, parameterForIt);
            LambdaExpression lambda = translator.TranslateFilterClause(filterClause);

            return(source.QueryableWhere(lambda));
        }
Ejemplo n.º 2
0
        /// <summary>Filters a query like a SQL WHERE clause does.</summary>
        /// <param name="service">Service with data and configuration.</param>
        /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param>
        /// <param name="source">Original source for query expression.</param>
        /// <returns>The composed query expression.</returns>
        internal static Expression Where(IDataService service, RequestDescription requestDescription, Expression source)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(source != null, "source != null");
            Debug.Assert(requestDescription != null, "requestDescription != null");

            FilterClause filterClause = new RequestExpressionParser(service, requestDescription).ParseFilter();

            if (filterClause == null)
            {
                return source;
            }

            bool filterQueryApplicable = requestDescription.TargetKind == RequestTargetKind.Resource
                                         || requestDescription.TargetKind == RequestTargetKind.OpenProperty
                                         || requestDescription.TargetKind == RequestTargetKind.ComplexObject
                                         || requestDescription.CountOption == RequestQueryCountOption.CountSegment;

            if (!filterQueryApplicable)
            {
                throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryFilterOptionNotApplicable);
            }

            Type queryElementType = source.ElementType();
            Debug.Assert(queryElementType != null, "queryElementType != null");

            ParameterExpression parameterForIt = Expression.Parameter(queryElementType, "it");
            Debug.Assert(
                (requestDescription.TargetResourceSet == null && (requestDescription.TargetResourceType == null || requestDescription.TargetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)) ||
                (requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.ResourceTypeKind == ResourceTypeKind.EntityType),
                "setForIt cannot be null if typeForIt is an entity type.");
            Debug.Assert(
                requestDescription.TargetResourceType == null && parameterForIt.Type == typeof(object) ||
                requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.InstanceType == parameterForIt.Type,
                "non-open type expressions should have a typeForIt");

            var translator = NodeToExpressionTranslator.Create(service, requestDescription, parameterForIt);
            LambdaExpression lambda = translator.TranslateFilterClause(filterClause);
            return source.QueryableWhere(lambda);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Builds the collection of ordering expressions including implicit ordering if paging is required at top level
        /// </summary>
        private void ObtainOrderingExpressions()
        {
            const String Comma = ",";
            const char Space = ' ';
            const String AscendingOrderIdentifier = "asc";
            const string QuestionMark = "?";
            const string EqualMark = "=";
            const string AndMark = "&";
            if (!string.IsNullOrEmpty(this.service.OperationContext.RequestMessage.GetQueryStringItem(XmlConstants.HttpQueryStringOrderBy)))
            {
                this.CheckSetQueryApplicable();
            }

            Debug.Assert(this.topLevelOrderingInfo == null, "Must only be called once per query");

            ResourceType rt = this.description.TargetResourceType;

            this.topLevelOrderingInfo = new OrderingInfo(this.IsStandardPaged);
            OrderByClause orderByClause = new RequestExpressionParser(this.service, this.description).ParseOrderBy();

            // We need to generate ordering expression(when we don't have top level $orderby), if either the result is paged, or we have
            // skip or top count request because in that case, the skip or top has to happen in
            // the expand provider. 
            if (orderByClause == null)
            {
                if (this.IsStandardPaged || this.topCount.HasValue || this.skipCount.HasValue)
                {
                    Uri requestUri = this.service.OperationContext.AbsoluteRequestUri;
                    StringBuilder orderBy = string.IsNullOrEmpty(requestUri.Query) ? new StringBuilder(requestUri.AbsoluteUri + QuestionMark) : new StringBuilder(requestUri.AbsoluteUri + AndMark);
                    orderBy.Append(XmlConstants.HttpQueryStringOrderBy + EqualMark);
                    String separator = String.Empty;
                    foreach (var keyProp in this.description.TargetResourceSet.GetKeyPropertiesForOrderBy())
                    {
                        orderBy.Append(separator).Append(keyProp.Name).Append(Space).Append(AscendingOrderIdentifier);
                        separator = Comma;
                    }

                    var uriParser = RequestUriProcessor.CreateUriParserWithBatchReferenceCallback(this.service, new Uri(orderBy.ToString()));

                    orderByClause = uriParser.ParseOrderBy();
                }
                else
                {
                    return;
                }
            }

            ParameterExpression elementParameter = Expression.Parameter(rt.InstanceType, "element");
            var translator = NodeToExpressionTranslator.Create(this.service, this.description, elementParameter);
            IEnumerable<OrderingExpression> ordering = translator.TranslateOrderBy(orderByClause);

            this.topLevelOrderingInfo.AddRange(ordering);

            if (this.IsStandardPaged)
            {
                this.description.SkipTokenExpressionCount = this.topLevelOrderingInfo.OrderingExpressions.Count;
                this.description.SkipTokenProperties = NeedSkipTokenVisitor.CollectSkipTokenProperties(this.topLevelOrderingInfo, rt);
            }
        }