Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / Providers / ExpandedProjectionNode.cs / 1407647 / ExpandedProjectionNode.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// Represents an expanded node in the tree of projections // for queries with $expand and/or $select. // // // @owner [....] //--------------------------------------------------------------------- namespace System.Data.Services.Providers { #region Namespaces using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; #endregion ///This class represents an expanded navigation property in the tree /// of projected properties. It is also used to represent the root of the projection tree. [DebuggerDisplay("ExpandedProjectionNode {PropertyName}")] internal class ExpandedProjectionNode : ProjectionNode { #region Private fields ///The resource set to which the expansion leads. ///If this node represents expanded navigation property, this is the resource set /// to which the expanded navigation property points to. /// If this node is the root node of the projection tree, this is the resource set /// for the root of the query results. private readonly ResourceSetWrapper resourceSetWrapper; ///Collection of information which describes the ordering for the results /// returned by this expanded property. ///This can be null in which case no ordering is to be applied. private readonly OrderingInfo orderingInfo; ///The filter expression to be applied to results returned by this expanded property. ///This can be null in which case no filter is to be applied. private readonly Expression filter; ///Number of results to skip for this node. ///null value means that no skip should be applied. private readonly int? skipCount; ///Maximum number of results to return for this node. ///null value means that all results should be returned. private readonly int? takeCount; ///Maximum number of results allowed for this node. Provider should use this only as a hint. /// It should return no less then maxResultsExpected + 1 results (assuming that number is available) /// so that the service can detect violation of the limit. ///null value means that no limit will be applied and thus all results available should be returned. private readonly int? maxResultsExpected; ///List of child nodes. private Listnodes; /// Internal field which is set to true once we have seen a projection including this expanded /// property. Otherwise set to false. ///This field is used to eliminate expanded nodes which are not projected and thus there /// would be no point in expanding them. private bool projectionFound; ///Flag which specifies if all child properties of this node should be projected. private bool projectAllImmediateProperties; ///Flag which specified is the entire expanded subtree of this node should be projected. private bool projectSubtree; #endregion #region Constructors ///Creates new instance of node representing expanded navigation property. /// The name of the property to project and expand. /// Thefor this property. Can only be null for the root node. /// The resource set to which the expansion leads. /// The ordering info for this node. null means no ordering to be applied. /// The filter for this node. null means no filter to be applied. /// Number of results to skip. null means no results to be skipped. /// Maximum number of results to return. null means return all available results. /// Maximum number of expected results. Hint that the provider should return /// at least maxResultsExpected + 1 results (if available). internal ExpandedProjectionNode( string propertyName, ResourceProperty property, ResourceSetWrapper resourceSetWrapper, OrderingInfo orderingInfo, Expression filter, int? skipCount, int? takeCount, int? maxResultsExpected) : base(propertyName, property) { Debug.Assert(resourceSetWrapper != null, "resourceSetWrapper != null"); Debug.Assert(property != null || propertyName.Length == 0, "We don't support open navigation properties."); this.resourceSetWrapper = resourceSetWrapper; this.orderingInfo = orderingInfo; this.filter = filter; this.skipCount = skipCount; this.takeCount = takeCount; this.maxResultsExpected = maxResultsExpected; this.nodes = new List (); } #endregion #region Public properties /// Collection of information which describes the ordering for the results /// returned by this expanded property. ///This can be null in which case no ordering is to be applied. public OrderingInfo OrderingInfo { get { return this.orderingInfo; } } ///The filter expression to be applied to results returned by this expanded property. ///This can be null in which case no filter is to be applied. public Expression Filter { get { return this.filter; } } ///Number of results to skip for this node. ///null value means that no skip should be applied. public int? SkipCount { get { return this.skipCount; } } ///Maximum number of results to return for this node. ///null value means that all results should be returned. public int? TakeCount { get { return this.takeCount; } } ///Maximum number of results allowed for this node. Provider should use this only as a hint. /// It should return no less then MaxResultsExpected + 1 results (assuming that number is available) /// so that the service can detect violation of the limit. ///null value means that no limit will be applied and thus all results available should be returned. public int? MaxResultsExpected { get { return this.maxResultsExpected; } } ///List of child nodes. public IEnumerableNodes { get { return this.nodes; } } /// Set to true if all properties of this node should be made part of the results. public bool ProjectAllProperties { get { return this.projectSubtree || this.ProjectAllImmediateProperties; } } #endregion #region Internal properties ///The resource set to which the expansion leads. ///If this node represents expanded navigation property, this is the resource set /// to which the expanded navigation property points to. /// If this node is the root node of the projection tree, this is the resource set /// for the root of the query results. /// This property is for internal use by components of the WCF Data Services /// to avoid unnecessary lookups of the wrapper from the ResourceSet property. internal ResourceSetWrapper ResourceSetWrapper { get { return this.resourceSetWrapper; } } ///The resource type in which all the entities expanded by this segment will be of. ///This is usually the resource type of the internal virtual ResourceType ResourceType { get { Debug.Assert(this.Property != null, "Derived class should override this if property can be null."); return this.Property.ResourceType; } } ///for this node, /// but it can also be a derived type of that resource type. /// This can happen if navigation property points to a resource set but uses a derived type. /// It can also happen if service operation returns entities from a given resource set /// but it returns derived types. Internal property which is set to true once we have seen a projection including this expanded /// property. Otherwise set to false. ///This property is used to eliminate expanded nodes which are not projected and thus there /// would be no point in expanding them. internal bool ProjectionFound { get { return this.projectionFound; } set { this.projectionFound = value; } } ///Flag which specifies if all child properties of this node should be projected. internal bool ProjectAllImmediateProperties { get { return this.projectAllImmediateProperties; } set { Debug.Assert(!value || this.projectionFound, "Marking node to include all child properties requires the node to be projected."); this.projectAllImmediateProperties = value; } } ///Whether this expanded node has a filter or a constraint on max results returns. internal bool HasFilterOrMaxResults { get { return this.Filter != null || this.MaxResultsExpected.HasValue; } } #endregion #region Internal methods ///Find a child node of a given property. /// The name of the property to find the child for. ///The child node if there's one for the specified internal ProjectionNode FindNode(string propertyName) { Debug.Assert(propertyName != null, "propertyName != null"); return this.nodes.FirstOrDefault( projectionNode => String.Equals(projectionNode.PropertyName, propertyName, StringComparison.Ordinal)); } ///or null /// if no such child was found. Adds a new child node to this node. /// The child node to add. internal void AddNode(ProjectionNode node) { Debug.Assert(node != null, "node != null"); Debug.Assert(this.FindNode(node.PropertyName) == null, "Trying to add a duplicate node."); this.nodes.Add(node); } ///Walks the subtree of this node and removes all nodes which were not marked projected. ///Used to remove unnecessary expanded nodes. internal void RemoveNonProjectedNodes() { for (int j = this.nodes.Count - 1; j >= 0; j--) { ExpandedProjectionNode expandedNode = this.nodes[j] as ExpandedProjectionNode; // Leave non-expanded properties there as they specify projections. if (expandedNode == null) { continue; } // If we are to project entire subtree, leave all expanded nodes in as well // otherwise remove the expanded nodes which are not marked as projected. if (!this.projectSubtree && !expandedNode.ProjectionFound) { // This removes the expandedNode from the tree (and all its children) this.nodes.RemoveAt(j); } else { expandedNode.RemoveNonProjectedNodes(); } } } ///Removes duplicates from the tree caused by wildcards and sorts the projected properties. ////// Examples /// $select=Orders, Orders/ID - get rid of the Orders/ID /// $select=Orders, Orders/* - get rid of the Orders/* /// $select=Orders/*, Orders/ID - get rid of the Orders/ID /// $select=Orders/*, Orders/OrderItems&$expand=Orders - get rid of the Orders/OrderItems (it's redundant to *) /// $select=Orders/*, Orders/OrderItems&$expand=Orders/OrderItems - leave as is, the Orders/OrderItems are expanded /// /// The sorting order is the same as the order in which the properties are enumerated on the owning type. /// This is to preserve the same order as if no projections occured. /// internal void ApplyWildcardsAndSort() { // If this segment was marked to include entire subtree // simply remove all children which are not expanded // and propagate the information to all expanded children. if (this.projectSubtree) { for (int j = this.nodes.Count - 1; j >= 0; j--) { ExpandedProjectionNode expandedNode = this.nodes[j] as ExpandedProjectionNode; if (expandedNode != null) { expandedNode.projectSubtree = true; expandedNode.ApplyWildcardsAndSort(); } else { this.nodes.RemoveAt(j); } } this.projectAllImmediateProperties = false; return; } for (int j = this.nodes.Count - 1; j >= 0; j--) { ExpandedProjectionNode expandedNode = this.nodes[j] as ExpandedProjectionNode; // If this node was marked to include all immediate properties, // remove all children which are not expanded. // That means they are either simple properties or nav. properties which // are not going to be expanded anyway. if (this.ProjectAllImmediateProperties && expandedNode == null) { this.nodes.RemoveAt(j); } else if (expandedNode != null) { expandedNode.ApplyWildcardsAndSort(); } } if (this.nodes.Count > 0) { // Sort the subsegments such that they have the same order as the properties // on the owning resource type. ResourceType resourceType = this.ResourceType; ListexistingNodes = this.nodes; this.nodes = new List (existingNodes.Count); foreach (ResourceProperty property in resourceType.Properties) { Debug.Assert( existingNodes.Where(node => node.Property == property).Count() <= 1, "Can't have more than one projection segment for a given property."); ProjectionNode projectionNode = existingNodes.FirstOrDefault( node => node.Property == property); if (projectionNode != null) { this.nodes.Add(projectionNode); } } // And then append any open properties sorted alphabetically // We sort these since we don't want client to be able to influence // the server behavior unless abo----ely necessary. List openPropertyProjectionNodes = existingNodes.Where(node => node.Property == null).ToList(); openPropertyProjectionNodes.Sort(new Comparison ((x, y) => { return String.Compare(x.PropertyName, y.PropertyName, StringComparison.Ordinal); })); this.nodes.AddRange(openPropertyProjectionNodes); Debug.Assert(this.nodes.Count == existingNodes.Count, "We didn't sort all the properties."); } } /// Marks the entire subtree as projected. ///This is used when there were no projections specified in the query /// to mark the entire tree as projected. internal void MarkSubtreeAsProjected() { this.projectSubtree = true; this.projectAllImmediateProperties = false; foreach (ProjectionNode node in this.nodes) { ExpandedProjectionNode expandedNode = node as ExpandedProjectionNode; if (expandedNode != null) { expandedNode.MarkSubtreeAsProjected(); } } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PropertyTabChangedEvent.cs
- StorageModelBuildProvider.cs
- BitArray.cs
- SqlTypesSchemaImporter.cs
- QueryParameter.cs
- MemberJoinTreeNode.cs
- TimelineCollection.cs
- EventWaitHandleSecurity.cs
- PeerApplication.cs
- ColorMatrix.cs
- MailWebEventProvider.cs
- XmlSubtreeReader.cs
- TypeForwardedToAttribute.cs
- HandleCollector.cs
- SizeLimitedCache.cs
- XPathChildIterator.cs
- VBIdentifierNameEditor.cs
- PropertyKey.cs
- OrthographicCamera.cs
- BindableTemplateBuilder.cs
- CommonProperties.cs
- BasicHttpSecurityElement.cs
- TransformGroup.cs
- BigInt.cs
- NameValueSectionHandler.cs
- ToolStripRenderer.cs
- querybuilder.cs
- TemplatedWizardStep.cs
- MenuItem.cs
- ModelVisual3D.cs
- WorkflowCreationContext.cs
- GatewayIPAddressInformationCollection.cs
- BookmarkScope.cs
- ResizeGrip.cs
- SizeAnimation.cs
- ServiceModelEnumValidatorAttribute.cs
- Viewport3DVisual.cs
- DrawingCollection.cs
- MetadataCollection.cs
- WebPartConnectionsEventArgs.cs
- NetworkAddressChange.cs
- IntPtr.cs
- SettingsProviderCollection.cs
- ProjectionQueryOptionExpression.cs
- CodeDirectoryCompiler.cs
- WebPartEditorCancelVerb.cs
- TextEffectResolver.cs
- QueryIntervalOp.cs
- QilInvokeLateBound.cs
- ZipIOExtraField.cs
- InkCanvas.cs
- storepermissionattribute.cs
- WebPartConnectionsDisconnectVerb.cs
- VerificationException.cs
- AutoResetEvent.cs
- _SingleItemRequestCache.cs
- glyphs.cs
- ObjectAssociationEndMapping.cs
- ControlCollection.cs
- UpdatePanelControlTrigger.cs
- DoubleStorage.cs
- Item.cs
- Task.cs
- WindowsImpersonationContext.cs
- CodeExporter.cs
- HelpKeywordAttribute.cs
- BamlReader.cs
- DynamicEntity.cs
- Boolean.cs
- Pen.cs
- Renderer.cs
- IdentifierService.cs
- EntityDescriptor.cs
- PresentationAppDomainManager.cs
- RelationshipEndCollection.cs
- DataView.cs
- MailBnfHelper.cs
- ExpressionConverter.cs
- ThreadPool.cs
- NameObjectCollectionBase.cs
- CorrelationManager.cs
- TemplateInstanceAttribute.cs
- Internal.cs
- SQLMembershipProvider.cs
- SimplePropertyEntry.cs
- ControlParameter.cs
- ConfigurationElementCollection.cs
- ColumnMapProcessor.cs
- XmlElementList.cs
- SuppressMergeCheckAttribute.cs
- ObjectMaterializedEventArgs.cs
- PageThemeParser.cs
- SmtpTransport.cs
- XmlCodeExporter.cs
- ImportOptions.cs
- ConfigsHelper.cs
- altserialization.cs
- DesignerCategoryAttribute.cs
- WebHeaderCollection.cs
- Utils.cs