/// <summary>Initializes a new RequestDescription based on an existing one.</summary> /// <param name="other">Other description to base new description on.</param> /// <param name="resultExpression">Query results for new request description.</param> /// <param name="rootProjectionNode">Projection segment describing the projections on the top level of the query.</param> internal RequestDescription( RequestDescription other, Expression resultExpression, RootProjectionNode rootProjectionNode) { Debug.Assert( resultExpression == null || other.SegmentInfos != null, "queryResults == null || other.SegmentInfos != null -- otherwise there isn't a segment in which to replace the query."); Debug.Assert( rootProjectionNode == null || resultExpression != null, "rootProjectionNode == null || queryResults != null -- otherwise there isn't a query to execute and expand"); this.rootProjectionNode = rootProjectionNode; this.containerName = other.ContainerName; this.mimeType = other.MimeType; this.resultUri = other.ResultUri; this.segmentInfos = other.SegmentInfos; this.CopyFrom(other); if (resultExpression != null) { this.LastSegmentInfo.RequestExpression = resultExpression; } }
/// <summary> /// Performs a depth-first walk down the expand tree, copying and adding to the current path as it goes. When the bottom of a path is reached, the path is added to the overall set of paths. /// </summary> /// <param name="currentPath">The current path so far for this depth-first traversal of the tree. Starts out null.</param> /// <param name="currentNode">The current node of the expand tree.</param> /// <param name="rootNode">The root node of the expand tree.</param> private void ExtractExpandPathSegmentCollections(ExpandSegmentCollection currentPath, ExpandedProjectionNode currentNode, RootProjectionNode rootNode) { ExpandSegmentCollection nextPath = null; foreach (ExpandedNavigationSelectItem expandItem in currentNode.SelectExpandClause.SelectedItems.OfType<ExpandedNavigationSelectItem>()) { rootNode.ExpansionsSpecified = true; if (currentPath == null) { nextPath = new ExpandSegmentCollection(); } else { // create a copy of the current path. nextPath = new ExpandSegmentCollection(currentPath.Count); nextPath.AddRange(currentPath); } var segment = this.CreateExpandSegment(expandItem, currentNode.ResourceType); nextPath.Add(segment); ExpandedProjectionNode childNode = currentNode.AddExpandedNode(segment, expandItem.SelectAndExpand); // if there are any derived expansions in the tree, set the rootNode.DerivedExpansionsSpecified to true. if (currentNode.HasExpandedPropertyOnDerivedType) { rootNode.ExpansionOnDerivedTypesSpecified = true; } this.ExtractExpandPathSegmentCollections(nextPath, childNode, rootNode); } if (nextPath == null && currentPath != null) { this.expandPaths.Add(currentPath); } }
/// <summary>Initializes a new <see cref="RequestQueryProcessor"/> instance.</summary> /// <param name="service">Service with data and configuration.</param> /// <param name="description">Description for request processed so far.</param> private RequestQueryProcessor(IDataService service, RequestDescription description) { this.service = service; this.description = description; #if DEBUG this.orderApplied = false; #endif this.skipCount = null; this.topCount = null; this.queryExpression = description.RequestExpression; this.setQueryApplicable = (description.TargetKind == RequestTargetKind.Resource && !description.IsSingleResult) || description.CountOption == RequestQueryCountOption.CountSegment; // Server Driven Paging is not considered for the following cases: // 1. Top level result is not or resource type or it is a single valued result. // 2. $count segment provided. // 3. Non-GET requests do not honor SDP. // 4. Only exception for Non-GET requests is if the request is coming from a Service // operation that returns a set of result values of entity type. this.pagingApplicable = (description.TargetKind == RequestTargetKind.Resource && !description.IsSingleResult) && (description.CountOption != RequestQueryCountOption.CountSegment) && !description.IsRequestForEnumServiceOperation && (service.OperationContext.RequestMessage.HttpVerb.IsQuery() || description.SegmentInfos[0].TargetSource == RequestTargetSource.ServiceOperation); this.appliedCustomPaging = false; this.rootProjectionNode = null; this.topLevelOrderingInfo = null; this.skipTokenExpressionBuilder = new SkipTokenExpressionBuilder(NodeToExpressionTranslator.Create(this.service, description, Expression.Parameter(typeof(object)))); }
/// <summary>Gets the root projection node or creates one if no one exists yet.</summary> /// <returns>The root node of the projection tree.</returns> private RootProjectionNode GetRootProjectionNode() { if (this.rootProjectionNode == null) { // Build the root of the projection and expansion tree this.rootProjectionNode = new RootProjectionNode( this.description.LastSegmentInfo.TargetResourceSet, this.topLevelOrderingInfo, null, this.skipCount, this.topCount, null, this.expandPaths, this.description.TargetResourceType, this.description.ExpandAndSelect.Clause); } return this.rootProjectionNode; }