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);
        }
Exemple #2
0
        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;
        }