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
- OpenTypeLayout.cs
- JapaneseCalendar.cs
- OrthographicCamera.cs
- DomainUpDown.cs
- CompositeFontFamily.cs
- WebFormDesignerActionService.cs
- ListViewItemEventArgs.cs
- GlobalDataBindingHandler.cs
- SQLGuid.cs
- SlipBehavior.cs
- ActiveDocumentEvent.cs
- MenuItemBinding.cs
- ParentQuery.cs
- FieldToken.cs
- EdmProperty.cs
- XamlWriterExtensions.cs
- XmlSchemaAppInfo.cs
- MimeXmlReflector.cs
- PkcsUtils.cs
- AbstractDataSvcMapFileLoader.cs
- LineSegment.cs
- ToolStripMenuItemDesigner.cs
- DateTimeConverter.cs
- ToolStripItemEventArgs.cs
- panel.cs
- UdpChannelFactory.cs
- TextBounds.cs
- DataGridViewRowCancelEventArgs.cs
- SqlFacetAttribute.cs
- HtmlEmptyTagControlBuilder.cs
- __FastResourceComparer.cs
- CheckPair.cs
- WindowsTooltip.cs
- ComponentChangedEvent.cs
- FileLevelControlBuilderAttribute.cs
- BrowserCapabilitiesFactory.cs
- DateTimeConstantAttribute.cs
- SafeRightsManagementSessionHandle.cs
- FormsAuthenticationModule.cs
- _ConnectOverlappedAsyncResult.cs
- VirtualPath.cs
- Executor.cs
- BooleanSwitch.cs
- DataTableMapping.cs
- Equal.cs
- WorkflowDesignerMessageFilter.cs
- ScaleTransform.cs
- XmlSchemaSimpleContentExtension.cs
- ToolboxItemFilterAttribute.cs
- DateTime.cs
- BadImageFormatException.cs
- DesignTableCollection.cs
- DiscoveryClientDocuments.cs
- StringPropertyBuilder.cs
- ToolStripRenderEventArgs.cs
- WinEventHandler.cs
- NamespaceCollection.cs
- DesignTimeDataBinding.cs
- QueryHandler.cs
- XPathAncestorIterator.cs
- RefType.cs
- ViewLoader.cs
- HandlerBase.cs
- Authorization.cs
- ImageUrlEditor.cs
- ReadOnlyHierarchicalDataSourceView.cs
- GcHandle.cs
- DeviceSpecificDialogCachedState.cs
- FixedElement.cs
- TcpTransportElement.cs
- KeyProperty.cs
- XPathArrayIterator.cs
- EventListenerClientSide.cs
- UpdatableWrapper.cs
- SymLanguageVendor.cs
- RuleSetCollection.cs
- ResourceDescriptionAttribute.cs
- GridViewHeaderRowPresenterAutomationPeer.cs
- StoryFragments.cs
- FilterFactory.cs
- ExtensionWindowResizeGrip.cs
- Win32Native.cs
- MarginCollapsingState.cs
- StrongName.cs
- EntityDescriptor.cs
- EdmFunctionAttribute.cs
- InputReport.cs
- FutureFactory.cs
- DataTableReader.cs
- DataGridColumnDropSeparator.cs
- BasicAsyncResult.cs
- FormViewCommandEventArgs.cs
- HwndSubclass.cs
- SpecularMaterial.cs
- DbConnectionOptions.cs
- DrawingGroup.cs
- GridViewCommandEventArgs.cs
- AdapterDictionary.cs
- Bidi.cs
- Misc.cs