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
- ResXFileRef.cs
- FunctionNode.cs
- Vector3dCollection.cs
- X500Name.cs
- MessageHeaderDescription.cs
- TimeoutValidationAttribute.cs
- CommandField.cs
- StylusPointPropertyUnit.cs
- ParenExpr.cs
- GridItem.cs
- QilGeneratorEnv.cs
- SpellerInterop.cs
- MatrixKeyFrameCollection.cs
- DocComment.cs
- LoggedException.cs
- SqlBulkCopyColumnMapping.cs
- StructuralCache.cs
- ReadWriteSpinLock.cs
- FullTextLine.cs
- MgmtResManager.cs
- DataGridViewToolTip.cs
- EntityDataSourceReferenceGroup.cs
- TabControlEvent.cs
- DesignerLinkAdapter.cs
- PackWebRequest.cs
- dtdvalidator.cs
- OleDbRowUpdatingEvent.cs
- DataSourceExpressionCollection.cs
- XmlValueConverter.cs
- ControlBuilderAttribute.cs
- FileSecurity.cs
- RbTree.cs
- NameTable.cs
- CurrencyManager.cs
- ApplicationId.cs
- SQLBytesStorage.cs
- BordersPage.cs
- StrokeCollectionConverter.cs
- Ticks.cs
- CharAnimationUsingKeyFrames.cs
- HighlightVisual.cs
- WaveHeader.cs
- StylusLogic.cs
- MeasureData.cs
- DataGridViewControlCollection.cs
- OleDbFactory.cs
- IConvertible.cs
- LocalBuilder.cs
- DateTimeAutomationPeer.cs
- DataMisalignedException.cs
- MissingManifestResourceException.cs
- FileDialogPermission.cs
- CodeVariableDeclarationStatement.cs
- ListBox.cs
- NativeActivityContext.cs
- AnnotationAdorner.cs
- ListViewItem.cs
- HtmlElementEventArgs.cs
- CodeStatementCollection.cs
- SpecialTypeDataContract.cs
- Misc.cs
- ProfessionalColors.cs
- XmlSchemaNotation.cs
- JsonStringDataContract.cs
- SwitchLevelAttribute.cs
- HttpTransportSecurity.cs
- AvTraceDetails.cs
- DataComponentGenerator.cs
- HMACMD5.cs
- HttpCapabilitiesBase.cs
- BaseDataBoundControl.cs
- Rotation3DAnimation.cs
- TransactionInformation.cs
- ReadOnlyDataSourceView.cs
- FilteredDataSetHelper.cs
- MetadataException.cs
- PenContext.cs
- Executor.cs
- AssemblyCache.cs
- Msec.cs
- AdornerHitTestResult.cs
- ManipulationDeltaEventArgs.cs
- DataColumnPropertyDescriptor.cs
- PersistenceProviderElement.cs
- DoubleUtil.cs
- _FixedSizeReader.cs
- CalloutQueueItem.cs
- SizeChangedInfo.cs
- ElementsClipboardData.cs
- HoistedLocals.cs
- ConfigurationStrings.cs
- Imaging.cs
- SubclassTypeValidator.cs
- BitmapVisualManager.cs
- TraceHandlerErrorFormatter.cs
- ThreadAttributes.cs
- AddingNewEventArgs.cs
- ISCIIEncoding.cs
- VisualSerializer.cs
- GPRECT.cs