Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Objects / Internal / ObjectFullSpanRewriter.cs / 2 / ObjectFullSpanRewriter.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupowner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Data.Common; using System.Data.Common.Utils; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; using System.Data.Objects.DataClasses; using System.Text; namespace System.Data.Objects.Internal { internal class ObjectFullSpanRewriter : ObjectSpanRewriter { ////// Represents a node in the 'Include' navigation property tree /// built from the list of SpanPaths on the Span object with which /// the FullSpanRewriter is constructed. /// private class SpanPathInfo { internal SpanPathInfo(EntityType declaringType) { this.DeclaringType = declaringType; } ////// The effective Entity type of this node in the tree /// internal EntityType DeclaringType; ////// Describes the navigation properties that should be retrieved /// from this node in the tree and the Include sub-paths that extend /// from each of those navigation properties /// internal DictionaryChildren; } /// /// Maintains a reference to the SpanPathInfo tree node representing the /// current position in the 'Include' path that is currently being expanded. /// private Stack_currentSpanPath = new Stack (); internal ObjectFullSpanRewriter(DbExpression toRewrite, Span span) : base(toRewrite) { Debug.Assert(span != null, "Span cannot be null"); Debug.Assert(span.SpanList.Count > 0, "At least one span path is required"); // Retrieve the effective 'T' of the ObjectQuery that produced // the Command Tree that is being rewritten. This could be either // literally 'T' or Collection . EntityType entityType = null; if (!TryGetEntityType(this.Query.ResultType, out entityType)) { // If the result type of the query is neither an Entity type nor a collection // type with an Entity element type, then full Span is currently not allowed. throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ObjectQuery_Span_IncludeRequiresEntityOrEntityCollection); } // Construct the SpanPathInfo navigation property tree using the // list of Include Span paths from the Span object: // Create a SpanPathInfo instance that represents the root of the tree // and takes its Entity type from the Entity type of the result type of the query. SpanPathInfo spanRoot = new SpanPathInfo(entityType); // Populate the tree of navigation properties based on the navigation property names // in the Span paths from the Span object. Commonly rooted span paths are merged, so // that paths of "Customer.Order" and "Customer.Address", for example, will share a // common SpanPathInfo for "Customer" in the Children collection of the root SpanPathInfo, // and that SpanPathInfo will contain one child for "Order" and another for "Address". foreach (Span.SpanPath path in span.SpanList) { AddSpanPath(spanRoot, path.Navigations); } // The 'current' span path is initialized to the root of the Include span tree _currentSpanPath.Push(spanRoot); } /// /// Populates the Include span tree with appropriate branches for the Include path /// represented by the specified list of navigation property names. /// /// The root SpanPathInfo /// A list of navigation property names that describes a single Include span path private void AddSpanPath(SpanPathInfo parentInfo, ListnavPropNames) { ConvertSpanPath(parentInfo, navPropNames, 0); } private void ConvertSpanPath(SpanPathInfo parentInfo, List navPropNames, int pos) { // Attempt to retrieve the next navigation property from the current entity type // using the name of the current navigation property in the Include path. NavigationProperty nextNavProp = null; if (!parentInfo.DeclaringType.NavigationProperties.TryGetValue(navPropNames[pos], true, out nextNavProp)) { // The navigation property name is not valid for this Entity type throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ObjectQuery_Span_NoNavProp(parentInfo.DeclaringType.FullName, navPropNames[pos])); } // The navigation property was retrieved, an entry for it must be ensured in the Children // collection of the parent SpanPathInfo instance. // If the parent's Children collection does not exist then instantiate it now: if (null == parentInfo.Children) { parentInfo.Children = new Dictionary (); } // If a sub-path that begins with the current navigation property name was already // encountered, then a SpanPathInfo for this navigation property may already exist // in the Children dictionary... SpanPathInfo nextChild = null; if (!parentInfo.Children.TryGetValue(nextNavProp, out nextChild)) { // ... otherwise, create a new SpanPathInfo instance that this navigation // property maps to and ensure its presence in the Children dictionary. nextChild = new SpanPathInfo(EntityTypeFromResultType(nextNavProp)); parentInfo.Children[nextNavProp] = nextChild; } // If this navigation property is not the end of the span path then // increment the position and recursively call ConvertSpanPath, specifying // the (retrieved or newly-created) SpanPathInfo of this navigation property // as the new 'parent' info. if (pos < navPropNames.Count - 1) { ConvertSpanPath(nextChild, navPropNames, pos + 1); } } /// /// Retrieves the Entity (result or element) type produced by a Navigation Property. /// /// The navigation property ////// The Entity type produced by the navigation property. /// This may be the immediate result type (if the result is at most one) /// or the element type of the result type, otherwise. /// private static EntityType EntityTypeFromResultType(NavigationProperty navProp) { EntityType retType = null; TryGetEntityType(navProp.TypeUsage, out retType); // Currently, navigation properties may only return an Entity or Collectionresult Debug.Assert(retType != null, "Navigation property has non-Entity and non-Entity collection result type?"); return retType; } /// /// Retrieves the Entity (result or element) type referenced by the specified TypeUsage, if /// its EdmType is an Entity type or a collection type with an Entity element type. /// /// The TypeUsage that provides the EdmType to examine /// The referenced Entity (element) type, if present. ////// private static bool TryGetEntityType(TypeUsage resultType, out EntityType entityType) { // If the result type is an Entity, then simply use that type. if (BuiltInTypeKind.EntityType == resultType.EdmType.BuiltInTypeKind) { entityType = (EntityType)resultType.EdmType; return true; } else if (BuiltInTypeKind.CollectionType == resultType.EdmType.BuiltInTypeKind) { // If the result type of the query is a collection, attempt to extract // the element type of the collection and determine if it is an Entity type. EdmType elementType = ((CollectionType)resultType.EdmType).TypeUsage.EdmType; if (BuiltInTypeKind.EntityType == elementType.BuiltInTypeKind) { entityType = (EntityType)elementType; return true; } } entityType = null; return false; } ///true if the specifiedis an Entity type or a /// collection type with an Entity element type; otherwise false . ////// Utility method to retrieve the 'To' AssociationEndMember of a NavigationProperty /// /// The navigation property ///The AssociationEndMember that is the target of the navigation operation represented by the NavigationProperty private AssociationEndMember GetNavigationPropertyTargetEnd(NavigationProperty property) { AssociationType relationship = this.Metadata.GetItem(property.RelationshipType.FullName, DataSpace.CSpace); Debug.Assert(relationship.AssociationEndMembers.Contains(property.ToEndMember.Name), "Association does not declare member referenced by Navigation property?"); return relationship.AssociationEndMembers[property.ToEndMember.Name]; } internal override SpanTrackingInfo CreateEntitySpanTrackingInfo(DbExpression expression, EntityType entityType) { SpanTrackingInfo tracking = new SpanTrackingInfo(); SpanPathInfo currentInfo = _currentSpanPath.Peek(); if (currentInfo.Children != null) { // The current SpanPathInfo instance on the top of the span path stack indicates // which navigation properties should be retrieved from this Entity-typed expression // and also specifies (in the form of child SpanPathInfo instances) which sub-paths // must be expanded for each of those navigation properties. // The SpanPathInfo instance may be the root instance or a SpanPathInfo that represents a sub-path. int idx = 1; // SpanRoot is always the first (zeroth) column, full- and relationship-span columns follow. foreach (KeyValuePair nextInfo in currentInfo.Children) { // If the tracking information was not initialized yet, do so now. if (null == tracking.ColumnDefinitions) { tracking = InitializeTrackingInfo(this.RelationshipSpan); } // Create a property expression that retrieves the specified navigation property from the Entity-typed expression. // Note that the expression is cloned since it may be used as the instance of multiple property expressions. DbExpression columnDef = expression.CommandTree.CreatePropertyExpression(nextInfo.Key, expression.Clone()); // Rewrite the result of the navigation property. This is required for two reasons: // 1. To continue spanning the current Include path. // 2. To apply relationship span to the Entity or EntityCollection produced by the navigation property, if necessary. // Consider an Include path of "Order" for a query that returns OrderLines - the Include'd Orders should have // their associated Customer relationship spanned. // Note that this will recursively call this method with the Entity type of the result of the // navigation property, which will in turn call loop through the sub-paths of this navigation // property and adjust the stack to track which Include path is being expanded and which // element of that path is considered 'current'. _currentSpanPath.Push(nextInfo.Value); columnDef = this.Rewrite(columnDef); _currentSpanPath.Pop(); // Add a new column to the tracked columns using the rewritten column definition tracking.ColumnDefinitions.Add(new KeyValuePair (tracking.ColumnNames.Next(), columnDef)); AssociationEndMember targetEnd = GetNavigationPropertyTargetEnd(nextInfo.Key); tracking.SpannedColumns[idx] = targetEnd; // If full span and relationship span are both required, a relationship span may be rendered // redundant by an already added full span. Therefore the association ends that have been expanded // as part of full span are tracked using a dictionary. if (this.RelationshipSpan) { tracking.FullSpannedEnds[targetEnd] = true; } idx++; } } return tracking; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupowner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Data.Common; using System.Data.Common.Utils; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; using System.Data.Objects.DataClasses; using System.Text; namespace System.Data.Objects.Internal { internal class ObjectFullSpanRewriter : ObjectSpanRewriter { ////// Represents a node in the 'Include' navigation property tree /// built from the list of SpanPaths on the Span object with which /// the FullSpanRewriter is constructed. /// private class SpanPathInfo { internal SpanPathInfo(EntityType declaringType) { this.DeclaringType = declaringType; } ////// The effective Entity type of this node in the tree /// internal EntityType DeclaringType; ////// Describes the navigation properties that should be retrieved /// from this node in the tree and the Include sub-paths that extend /// from each of those navigation properties /// internal DictionaryChildren; } /// /// Maintains a reference to the SpanPathInfo tree node representing the /// current position in the 'Include' path that is currently being expanded. /// private Stack_currentSpanPath = new Stack (); internal ObjectFullSpanRewriter(DbExpression toRewrite, Span span) : base(toRewrite) { Debug.Assert(span != null, "Span cannot be null"); Debug.Assert(span.SpanList.Count > 0, "At least one span path is required"); // Retrieve the effective 'T' of the ObjectQuery that produced // the Command Tree that is being rewritten. This could be either // literally 'T' or Collection . EntityType entityType = null; if (!TryGetEntityType(this.Query.ResultType, out entityType)) { // If the result type of the query is neither an Entity type nor a collection // type with an Entity element type, then full Span is currently not allowed. throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ObjectQuery_Span_IncludeRequiresEntityOrEntityCollection); } // Construct the SpanPathInfo navigation property tree using the // list of Include Span paths from the Span object: // Create a SpanPathInfo instance that represents the root of the tree // and takes its Entity type from the Entity type of the result type of the query. SpanPathInfo spanRoot = new SpanPathInfo(entityType); // Populate the tree of navigation properties based on the navigation property names // in the Span paths from the Span object. Commonly rooted span paths are merged, so // that paths of "Customer.Order" and "Customer.Address", for example, will share a // common SpanPathInfo for "Customer" in the Children collection of the root SpanPathInfo, // and that SpanPathInfo will contain one child for "Order" and another for "Address". foreach (Span.SpanPath path in span.SpanList) { AddSpanPath(spanRoot, path.Navigations); } // The 'current' span path is initialized to the root of the Include span tree _currentSpanPath.Push(spanRoot); } /// /// Populates the Include span tree with appropriate branches for the Include path /// represented by the specified list of navigation property names. /// /// The root SpanPathInfo /// A list of navigation property names that describes a single Include span path private void AddSpanPath(SpanPathInfo parentInfo, ListnavPropNames) { ConvertSpanPath(parentInfo, navPropNames, 0); } private void ConvertSpanPath(SpanPathInfo parentInfo, List navPropNames, int pos) { // Attempt to retrieve the next navigation property from the current entity type // using the name of the current navigation property in the Include path. NavigationProperty nextNavProp = null; if (!parentInfo.DeclaringType.NavigationProperties.TryGetValue(navPropNames[pos], true, out nextNavProp)) { // The navigation property name is not valid for this Entity type throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ObjectQuery_Span_NoNavProp(parentInfo.DeclaringType.FullName, navPropNames[pos])); } // The navigation property was retrieved, an entry for it must be ensured in the Children // collection of the parent SpanPathInfo instance. // If the parent's Children collection does not exist then instantiate it now: if (null == parentInfo.Children) { parentInfo.Children = new Dictionary (); } // If a sub-path that begins with the current navigation property name was already // encountered, then a SpanPathInfo for this navigation property may already exist // in the Children dictionary... SpanPathInfo nextChild = null; if (!parentInfo.Children.TryGetValue(nextNavProp, out nextChild)) { // ... otherwise, create a new SpanPathInfo instance that this navigation // property maps to and ensure its presence in the Children dictionary. nextChild = new SpanPathInfo(EntityTypeFromResultType(nextNavProp)); parentInfo.Children[nextNavProp] = nextChild; } // If this navigation property is not the end of the span path then // increment the position and recursively call ConvertSpanPath, specifying // the (retrieved or newly-created) SpanPathInfo of this navigation property // as the new 'parent' info. if (pos < navPropNames.Count - 1) { ConvertSpanPath(nextChild, navPropNames, pos + 1); } } /// /// Retrieves the Entity (result or element) type produced by a Navigation Property. /// /// The navigation property ////// The Entity type produced by the navigation property. /// This may be the immediate result type (if the result is at most one) /// or the element type of the result type, otherwise. /// private static EntityType EntityTypeFromResultType(NavigationProperty navProp) { EntityType retType = null; TryGetEntityType(navProp.TypeUsage, out retType); // Currently, navigation properties may only return an Entity or Collectionresult Debug.Assert(retType != null, "Navigation property has non-Entity and non-Entity collection result type?"); return retType; } /// /// Retrieves the Entity (result or element) type referenced by the specified TypeUsage, if /// its EdmType is an Entity type or a collection type with an Entity element type. /// /// The TypeUsage that provides the EdmType to examine /// The referenced Entity (element) type, if present. ////// private static bool TryGetEntityType(TypeUsage resultType, out EntityType entityType) { // If the result type is an Entity, then simply use that type. if (BuiltInTypeKind.EntityType == resultType.EdmType.BuiltInTypeKind) { entityType = (EntityType)resultType.EdmType; return true; } else if (BuiltInTypeKind.CollectionType == resultType.EdmType.BuiltInTypeKind) { // If the result type of the query is a collection, attempt to extract // the element type of the collection and determine if it is an Entity type. EdmType elementType = ((CollectionType)resultType.EdmType).TypeUsage.EdmType; if (BuiltInTypeKind.EntityType == elementType.BuiltInTypeKind) { entityType = (EntityType)elementType; return true; } } entityType = null; return false; } ///true if the specifiedis an Entity type or a /// collection type with an Entity element type; otherwise false . ////// Utility method to retrieve the 'To' AssociationEndMember of a NavigationProperty /// /// The navigation property ///The AssociationEndMember that is the target of the navigation operation represented by the NavigationProperty private AssociationEndMember GetNavigationPropertyTargetEnd(NavigationProperty property) { AssociationType relationship = this.Metadata.GetItem(property.RelationshipType.FullName, DataSpace.CSpace); Debug.Assert(relationship.AssociationEndMembers.Contains(property.ToEndMember.Name), "Association does not declare member referenced by Navigation property?"); return relationship.AssociationEndMembers[property.ToEndMember.Name]; } internal override SpanTrackingInfo CreateEntitySpanTrackingInfo(DbExpression expression, EntityType entityType) { SpanTrackingInfo tracking = new SpanTrackingInfo(); SpanPathInfo currentInfo = _currentSpanPath.Peek(); if (currentInfo.Children != null) { // The current SpanPathInfo instance on the top of the span path stack indicates // which navigation properties should be retrieved from this Entity-typed expression // and also specifies (in the form of child SpanPathInfo instances) which sub-paths // must be expanded for each of those navigation properties. // The SpanPathInfo instance may be the root instance or a SpanPathInfo that represents a sub-path. int idx = 1; // SpanRoot is always the first (zeroth) column, full- and relationship-span columns follow. foreach (KeyValuePair nextInfo in currentInfo.Children) { // If the tracking information was not initialized yet, do so now. if (null == tracking.ColumnDefinitions) { tracking = InitializeTrackingInfo(this.RelationshipSpan); } // Create a property expression that retrieves the specified navigation property from the Entity-typed expression. // Note that the expression is cloned since it may be used as the instance of multiple property expressions. DbExpression columnDef = expression.CommandTree.CreatePropertyExpression(nextInfo.Key, expression.Clone()); // Rewrite the result of the navigation property. This is required for two reasons: // 1. To continue spanning the current Include path. // 2. To apply relationship span to the Entity or EntityCollection produced by the navigation property, if necessary. // Consider an Include path of "Order" for a query that returns OrderLines - the Include'd Orders should have // their associated Customer relationship spanned. // Note that this will recursively call this method with the Entity type of the result of the // navigation property, which will in turn call loop through the sub-paths of this navigation // property and adjust the stack to track which Include path is being expanded and which // element of that path is considered 'current'. _currentSpanPath.Push(nextInfo.Value); columnDef = this.Rewrite(columnDef); _currentSpanPath.Pop(); // Add a new column to the tracked columns using the rewritten column definition tracking.ColumnDefinitions.Add(new KeyValuePair (tracking.ColumnNames.Next(), columnDef)); AssociationEndMember targetEnd = GetNavigationPropertyTargetEnd(nextInfo.Key); tracking.SpannedColumns[idx] = targetEnd; // If full span and relationship span are both required, a relationship span may be rendered // redundant by an already added full span. Therefore the association ends that have been expanded // as part of full span are tracked using a dictionary. if (this.RelationshipSpan) { tracking.FullSpannedEnds[targetEnd] = true; } idx++; } } return tracking; } } } // 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
- PeekCompletedEventArgs.cs
- HostingEnvironmentException.cs
- CalendarButtonAutomationPeer.cs
- ImportDesigner.xaml.cs
- UrlRoutingHandler.cs
- ConstrainedDataObject.cs
- SID.cs
- WebPartZone.cs
- TreeViewTemplateSelector.cs
- LiteralControl.cs
- AlphaSortedEnumConverter.cs
- PageThemeParser.cs
- EasingQuaternionKeyFrame.cs
- TempFiles.cs
- activationcontext.cs
- ObjectKeyFrameCollection.cs
- Crypto.cs
- OuterGlowBitmapEffect.cs
- CustomErrorsSectionWrapper.cs
- ValidationHelper.cs
- DbParameterCollection.cs
- UIElementParaClient.cs
- PrintPreviewDialog.cs
- TableRowCollection.cs
- ListControlActionList.cs
- RadioButtonRenderer.cs
- OdbcPermission.cs
- ProxyAttribute.cs
- AmbiguousMatchException.cs
- ToolStripDropDownItem.cs
- StrokeCollection.cs
- TraceSection.cs
- Mapping.cs
- LicFileLicenseProvider.cs
- ExpressionBuilder.cs
- CqlIdentifiers.cs
- SystemInfo.cs
- TextOnlyOutput.cs
- Quaternion.cs
- DataContract.cs
- Soap12ServerProtocol.cs
- UIElementCollection.cs
- IndentedWriter.cs
- TransportChannelListener.cs
- SecurityUniqueId.cs
- _ContextAwareResult.cs
- SimpleRecyclingCache.cs
- OrthographicCamera.cs
- PnrpPermission.cs
- DelayDesigner.cs
- PathFigureCollection.cs
- COSERVERINFO.cs
- DataChangedEventManager.cs
- MenuTracker.cs
- Light.cs
- UiaCoreTypesApi.cs
- ItemMap.cs
- UIPropertyMetadata.cs
- FormViewDeleteEventArgs.cs
- TextProviderWrapper.cs
- UniqueIdentifierService.cs
- DefaultBindingPropertyAttribute.cs
- PublisherMembershipCondition.cs
- DataBindingCollectionConverter.cs
- XPathDescendantIterator.cs
- QuaternionIndependentAnimationStorage.cs
- Group.cs
- PropertyItemInternal.cs
- SpeechRecognitionEngine.cs
- EmbeddedMailObject.cs
- BitmapEffectDrawingContent.cs
- RelatedView.cs
- ObjectDisposedException.cs
- EnterpriseServicesHelper.cs
- DbConnectionPoolIdentity.cs
- ActivityBuilderHelper.cs
- DebugControllerThread.cs
- XmlDocumentSchema.cs
- TimerEventSubscription.cs
- CssTextWriter.cs
- EventSourceCreationData.cs
- TypefaceMap.cs
- NotImplementedException.cs
- UserMapPath.cs
- RowsCopiedEventArgs.cs
- RegisteredScript.cs
- EnumerableRowCollectionExtensions.cs
- XmlArrayItemAttribute.cs
- PolicyUnit.cs
- ExpandSegmentCollection.cs
- HtmlWindow.cs
- OracleDataAdapter.cs
- WebServiceTypeData.cs
- PeerUnsafeNativeCryptMethods.cs
- DBDataPermissionAttribute.cs
- MetabaseSettingsIis7.cs
- RangeBase.cs
- StylusDownEventArgs.cs
- ModelItemDictionary.cs
- TransactionScopeDesigner.cs