private DbExpression RewriteEntity(DbExpression expression, EntityType entityType) { if (DbExpressionKind.NewInstance == expression.ExpressionKind) { return(expression); } ++this._spanCount; int spanCount = this._spanCount; ObjectSpanRewriter.SpanTrackingInfo spanTrackingInfo = this.CreateEntitySpanTrackingInfo(expression, entityType); List <KeyValuePair <AssociationEndMember, AssociationEndMember> > relationshipSpanEnds = this.GetRelationshipSpanEnds(entityType); if (relationshipSpanEnds != null) { if (spanTrackingInfo.ColumnDefinitions == null) { spanTrackingInfo = this.InitializeTrackingInfo(false); } int index = spanTrackingInfo.ColumnDefinitions.Count + 1; foreach (KeyValuePair <AssociationEndMember, AssociationEndMember> keyValuePair in relationshipSpanEnds) { if (spanTrackingInfo.FullSpannedEnds == null || !spanTrackingInfo.FullSpannedEnds.ContainsKey(keyValuePair.Value)) { DbExpression source = (DbExpression)null; if (!this.TryGetNavigationSource(keyValuePair.Value, out source)) { source = (DbExpression)expression.GetEntityRef().NavigateAllowingAllRelationshipsInSameTypeHierarchy((RelationshipEndMember)keyValuePair.Key, (RelationshipEndMember)keyValuePair.Value); } spanTrackingInfo.ColumnDefinitions.Add(new KeyValuePair <string, DbExpression>(spanTrackingInfo.ColumnNames.Next(), source)); spanTrackingInfo.SpannedColumns[index] = keyValuePair.Value; ++index; } } } if (spanTrackingInfo.ColumnDefinitions == null) { --this._spanCount; return(expression); } spanTrackingInfo.ColumnDefinitions.Insert(0, new KeyValuePair <string, DbExpression>(string.Format((IFormatProvider)CultureInfo.InvariantCulture, "Span{0}_SpanRoot", (object)spanCount), expression)); DbExpression dbExpression = (DbExpression)DbExpressionBuilder.NewRow((IEnumerable <KeyValuePair <string, DbExpression> >)spanTrackingInfo.ColumnDefinitions); this.AddSpanMap((RowType)dbExpression.ResultType.EdmType, spanTrackingInfo.SpannedColumns); return(dbExpression); }
private DbExpression RewriteEntity(DbExpression expression, EntityType entityType) { // If the expression is an Entity constructor, spanning will not produce any useful results // (null for an Entity/Ref navigation property, or an empty collection for a Collection // of Entity/Ref navigation property) since a Ref produced from the constructed Entity // will not indicate an Entity set, and therefore no Ref created against any Entity set // in the container can possibly be a match for it. if (DbExpressionKind.NewInstance == expression.ExpressionKind) { return(expression); } // Save the span count for later use. _spanCount++; int thisSpan = _spanCount; SpanTrackingInfo tracking = CreateEntitySpanTrackingInfo(expression, entityType); // If relationship span is required then attempt to span any appropriate relationship ends. List <KeyValuePair <AssociationEndMember, AssociationEndMember> > relationshipSpans = null; relationshipSpans = GetRelationshipSpanEnds(entityType); // Is the Entity type of this expression valid as the source of at least one relationship span? if (relationshipSpans != null) { // If the span tracking information was not initialized by CreateEntitySpanTrackingInfo, // then do so now as relationship span rewrites need to be tracked. if (null == tracking.ColumnDefinitions) { tracking = InitializeTrackingInfo(false); } // Track column index to span information, starting at the current column count (which could be zero) plus 1. // 1 is added because the column containing the root entity will be added later to provide column zero. int idx = tracking.ColumnDefinitions.Count + 1; // For all applicable relationship spans that were identified... foreach (KeyValuePair <AssociationEndMember, AssociationEndMember> relSpan in relationshipSpans) { // If the specified association end member was already full-spanned then the full entity // will be returned in the query and there is no need to relationship-span this end to produce // another result column that contains the Entity key of the full entity. // Hence the relationship span is only added if there are no full-span columns or the full-span // columns do not indicate that they include the target association end member of this relationship span. if (null == tracking.FullSpannedEnds || !tracking.FullSpannedEnds.ContainsKey(relSpan.Value)) { // If the source Ref is already available, because the currently spanned Entity is // the result of a Relationship Navigation operation from that Ref, then use the source // Ref directly rather than introducing a new Navigation operation. DbExpression columnDef = null; if (!TryGetNavigationSource(relSpan.Value, out columnDef)) { // Add a new column defined by the navigation required to reach the targeted association end // and update the column -> association end map to include an entry for this new column. DbExpression navSource = expression.GetEntityRef(); columnDef = navSource.NavigateAllowingAllRelationshipsInSameTypeHierarchy(relSpan.Key, relSpan.Value); } tracking.ColumnDefinitions.Add( new KeyValuePair <string, DbExpression>( tracking.ColumnNames.Next(), columnDef ) ); tracking.SpannedColumns[idx] = relSpan.Value; // Increment the tracked column count idx++; } } } // If no spanned columns have been added then simply return the original expression if (null == tracking.ColumnDefinitions) { _spanCount--; return(expression); } // Add the original entity-producing expression as the first (root) span column. tracking.ColumnDefinitions.Insert( 0, new KeyValuePair <string, DbExpression>( string.Format(CultureInfo.InvariantCulture, "Span{0}_SpanRoot", thisSpan), expression ) ); // Create the span row-producing NewInstanceExpression from which the span RowType can be retrieved. DbExpression spannedExpression = DbExpressionBuilder.NewRow(tracking.ColumnDefinitions); // Update the rowtype -> spaninfo map for the newly created row type instance. RowType spanRowType = (RowType)spannedExpression.ResultType.EdmType; AddSpanMap(spanRowType, tracking.SpannedColumns); // Return the rewritten expression return(spannedExpression); }
private DbExpression RewriteEntity(DbExpression expression, EntityType entityType) { // If the expression is an Entity constructor, spanning will not produce any useful results // (null for an Entity/Ref navigation property, or an empty collection for a Collection // of Entity/Ref navigation property) since a Ref produced from the constructed Entity // will not indicate an Entity set, and therefore no Ref created against any Entity set // in the container can possibly be a match for it. if (DbExpressionKind.NewInstance == expression.ExpressionKind) { return expression; } // Save the span count for later use. _spanCount++; int thisSpan = _spanCount; SpanTrackingInfo tracking = CreateEntitySpanTrackingInfo(expression, entityType); // If relationship span is required then attempt to span any appropriate relationship ends. List<KeyValuePair<AssociationEndMember, AssociationEndMember>> relationshipSpans = null; relationshipSpans = GetRelationshipSpanEnds(entityType); // Is the Entity type of this expression valid as the source of at least one relationship span? if (relationshipSpans != null) { // If the span tracking information was not initialized by CreateEntitySpanTrackingInfo, // then do so now as relationship span rewrites need to be tracked. if (null == tracking.ColumnDefinitions) { tracking = InitializeTrackingInfo(false); } // Track column index to span information, starting at the current column count (which could be zero) plus 1. // 1 is added because the column containing the root entity will be added later to provide column zero. int idx = tracking.ColumnDefinitions.Count + 1; // For all applicable relationship spans that were identified... foreach (KeyValuePair<AssociationEndMember, AssociationEndMember> relSpan in relationshipSpans) { // If the specified association end member was already full-spanned then the full entity // will be returned in the query and there is no need to relationship-span this end to produce // another result column that contains the Entity key of the full entity. // Hence the relationship span is only added if there are no full-span columns or the full-span // columns do not indicate that they include the target association end member of this relationship span. if( null == tracking.FullSpannedEnds || !tracking.FullSpannedEnds.ContainsKey(relSpan.Value)) { // If the source Ref is already available, because the currently spanned Entity is // the result of a Relationship Navigation operation from that Ref, then use the source // Ref directly rather than introducing a new Navigation operation. DbExpression columnDef = null; if(!TryGetNavigationSource(relSpan.Value, out columnDef)) { // Add a new column defined by the navigation required to reach the targeted association end // and update the column -> association end map to include an entry for this new column. DbExpression navSource = expression.GetEntityRef(); columnDef = navSource.NavigateAllowingAllRelationshipsInSameTypeHierarchy(relSpan.Key, relSpan.Value); } tracking.ColumnDefinitions.Add( new KeyValuePair<string, DbExpression>( tracking.ColumnNames.Next(), columnDef ) ); tracking.SpannedColumns[idx] = relSpan.Value; // Increment the tracked column count idx++; } } } // If no spanned columns have been added then simply return the original expression if (null == tracking.ColumnDefinitions) { _spanCount--; return expression; } // Add the original entity-producing expression as the first (root) span column. tracking.ColumnDefinitions.Insert( 0, new KeyValuePair<string, DbExpression>( string.Format(CultureInfo.InvariantCulture, "Span{0}_SpanRoot", thisSpan), expression ) ); // Create the span row-producing NewInstanceExpression from which the span RowType can be retrieved. DbExpression spannedExpression = DbExpressionBuilder.NewRow(tracking.ColumnDefinitions); // Update the rowtype -> spaninfo map for the newly created row type instance. RowType spanRowType = (RowType)spannedExpression.ResultType.EdmType; AddSpanMap(spanRowType, tracking.SpannedColumns); // Return the rewritten expression return spannedExpression; }