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
- SQLDoubleStorage.cs
- DataGridViewButtonCell.cs
- SqlDataRecord.cs
- PcmConverter.cs
- GlyphRunDrawing.cs
- DataGridToolTip.cs
- MarginsConverter.cs
- TableLayoutColumnStyleCollection.cs
- TextUtf8RawTextWriter.cs
- PointConverter.cs
- QueryTaskGroupState.cs
- WindowsClientElement.cs
- ReversePositionQuery.cs
- SvcMapFile.cs
- PersistChildrenAttribute.cs
- DataGridViewRowHeaderCell.cs
- ReflectionPermission.cs
- DiscreteKeyFrames.cs
- Message.cs
- TemplateBuilder.cs
- FrameworkElementFactoryMarkupObject.cs
- ProxyWebPartConnectionCollection.cs
- ManualResetEvent.cs
- ReachIDocumentPaginatorSerializerAsync.cs
- SqlExpressionNullability.cs
- TaskSchedulerException.cs
- SoapFormatterSinks.cs
- LicFileLicenseProvider.cs
- RepeaterItemCollection.cs
- UrlEncodedParameterWriter.cs
- PerCallInstanceContextProvider.cs
- EncodingDataItem.cs
- PropertyEntry.cs
- ListViewItem.cs
- SoapUnknownHeader.cs
- ExpandCollapsePattern.cs
- BuildProviderInstallComponent.cs
- TextEditorSpelling.cs
- LoadWorkflowAsyncResult.cs
- SqlCaseSimplifier.cs
- WebServiceEnumData.cs
- FileEnumerator.cs
- RpcCryptoRequest.cs
- ResXDataNode.cs
- PropertyRecord.cs
- _SSPIWrapper.cs
- ProviderUtil.cs
- mongolianshape.cs
- PhysicalFontFamily.cs
- CodeBlockBuilder.cs
- Journaling.cs
- VisualBasic.cs
- Point3DIndependentAnimationStorage.cs
- TextEditorSpelling.cs
- InProcStateClientManager.cs
- SqlBulkCopyColumnMapping.cs
- GradientSpreadMethodValidation.cs
- EdmConstants.cs
- HiddenFieldPageStatePersister.cs
- Pen.cs
- XmlReflectionImporter.cs
- DataSourceView.cs
- ValidationErrorEventArgs.cs
- BaseCollection.cs
- MsmqIntegrationProcessProtocolHandler.cs
- AbstractExpressions.cs
- HideDisabledControlAdapter.cs
- SpellCheck.cs
- UniqueCodeIdentifierScope.cs
- ControlCachePolicy.cs
- TypeForwardedToAttribute.cs
- Table.cs
- CustomExpression.cs
- GatewayIPAddressInformationCollection.cs
- diagnosticsswitches.cs
- XamlSerializerUtil.cs
- DataBinder.cs
- ContainerControl.cs
- Literal.cs
- ObjectPropertyMapping.cs
- DbConnectionFactory.cs
- FixedTextSelectionProcessor.cs
- AstTree.cs
- GetCryptoTransformRequest.cs
- TargetParameterCountException.cs
- ObjectPersistData.cs
- InlineObject.cs
- WebBrowserSiteBase.cs
- ControlIdConverter.cs
- mansign.cs
- ParagraphVisual.cs
- SymDocumentType.cs
- OutputCacheProfileCollection.cs
- PropertyRecord.cs
- BaseDataListDesigner.cs
- Group.cs
- BuildManager.cs
- TraceUtils.cs
- QueueProcessor.cs
- MenuStrip.cs