예제 #1
0
        /// <summary>
        /// Gets the expected payload type for a request to the given uri
        /// </summary>
        /// <param name="requestUri">The request uri</param>
        /// <returns>The expected payload type</returns>
        public static ODataPayloadElementType GetExpectedPayloadType(this ODataUri requestUri)
        {
            if (requestUri.Segments.OfType <UnrecognizedSegment>().Any())
            {
                return(ODataPayloadElementType.Unknown);
            }

            if (requestUri.IsMetadata())
            {
                return(ODataPayloadElementType.MetadataPayloadElement);
            }

            if (requestUri.IsBatch())
            {
                return(ODataPayloadElementType.BatchResponsePayload);
            }

            if (requestUri.IsCount() || requestUri.IsPropertyValue() || requestUri.IsMediaResource() || requestUri.IsNamedStream())
            {
                return(ODataPayloadElementType.PrimitiveValue);
            }

            if (requestUri.IsEntity())
            {
                return(ODataPayloadElementType.EntityInstance);
            }

            if (requestUri.IsEntitySet())
            {
                return(ODataPayloadElementType.EntitySetInstance);
            }

            if (requestUri.IsEntityReferenceLink())
            {
                return(requestUri.GetExpectedLinkPayloadType());
            }

            if (requestUri.IsProperty())
            {
                var property = requestUri.Segments.OfType <PropertySegment>().Last();
                return(property.Property.GetExpectedPayloadType());
            }

            if (requestUri.IsServiceOperation() || requestUri.IsAction())
            {
                var serviceOp = requestUri.Segments.OfType <FunctionSegment>().Last();
                return(serviceOp.Function.GetExpectedPayloadType());
            }

            return(ODataPayloadElementType.Unknown);
        }
예제 #2
0
        /// <summary>
        /// Processes the given uri and produces an expected value according to the conventions of an OData server implementation
        /// </summary>
        /// <param name="uri">The uri to process</param>
        /// <param name="applySelectAndExpand">A value indicating whether or not $select and $expand should be applied to the query values</param>
        /// <param name="applyPaging">A value indicating whether server-driven paging should be applied to the query values</param>
        /// <returns>The value resulting from processing the uri</returns>
        public QueryValue Evaluate(ODataUri uri, bool applySelectAndExpand, bool applyPaging)
        {
            this.applyPagingInExpands = applyPaging;
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");
            ExceptionUtilities.CheckCollectionNotEmpty(uri.Segments, "uri.Segments");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            this.currentUri = uri;
            this.shouldLastSegmentBeSingleton = false;

            applyPaging &= uri.TryGetExpectedEntitySet(out this.expectedEntitySet);

            if (applyPaging)
            {
                // compute the expected page size for this request based on the existence of a universal page size or set-specific page size
                this.expectedPageSize = this.expectedEntitySet.GetEffectivePageSize();
            }
            else
            {
                this.expectedPageSize = null;
            }

            var query = this.BuildQueryFromSegments();
            ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

            // we explicitly do not process expand or select here because they do not affect the number of rows returned or their ordering
            query = this.ProcessFilter(query);
            ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

            if (uri.IsEntitySet())
            {
                // TODO: skip-token processing should happen before ordering
                query = this.ProcessOrderBy(query);
                ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

                query = this.ProcessSkipAndTop(query);
                ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);
            }

            // handle $count requests
            if (uri.IsCount())
            {
                query = query.LongCount();
            }

            // need to resolve types since we constructed new QueryExpression tree
            var resolvedQuery = this.QueryResolver.Resolve(query);

            var value = this.Evaluator.Evaluate(resolvedQuery);
            ExceptionUtilities.CheckObjectNotNull(value, "Could not evaluate query '{0}'", query);
            ExceptionUtilities.Assert(value.EvaluationError == null, "Query evaluation produced an error: {0}", value.EvaluationError);

            // post-process the result to defer properties that were not expanded
            if (applySelectAndExpand)
            {
                value = this.ApplySelectAndExpand(uri, value);
            }

            // fixup for key expressions that should return singletons
            if (this.shouldLastSegmentBeSingleton)
            {
                value = EnsureLastSegmentIsSingletonOrNull(value);
            }

            this.currentUri = null;
            this.expectedEntitySet = null;
            this.expectedPageSize = null;

            return value;
        }