private List <KeyValuePair <AssociationEndMember, AssociationEndMember> > GetRelationshipSpanEnds(
            EntityType entityType)
        {
            List <KeyValuePair <AssociationEndMember, AssociationEndMember> > keyValuePairList = (List <KeyValuePair <AssociationEndMember, AssociationEndMember> >)null;

            if (this._relationshipSpan)
            {
                foreach (AssociationType associationType in this._tree.MetadataWorkspace.GetItems <AssociationType>(DataSpace.CSpace))
                {
                    if (2 == associationType.AssociationEndMembers.Count)
                    {
                        AssociationEndMember associationEndMember1 = associationType.AssociationEndMembers[0];
                        AssociationEndMember associationEndMember2 = associationType.AssociationEndMembers[1];
                        if (ObjectSpanRewriter.IsValidRelationshipSpan(entityType, associationType, associationEndMember1, associationEndMember2))
                        {
                            if (keyValuePairList == null)
                            {
                                keyValuePairList = new List <KeyValuePair <AssociationEndMember, AssociationEndMember> >();
                            }
                            keyValuePairList.Add(new KeyValuePair <AssociationEndMember, AssociationEndMember>(associationEndMember1, associationEndMember2));
                        }
                        if (ObjectSpanRewriter.IsValidRelationshipSpan(entityType, associationType, associationEndMember2, associationEndMember1))
                        {
                            if (keyValuePairList == null)
                            {
                                keyValuePairList = new List <KeyValuePair <AssociationEndMember, AssociationEndMember> >();
                            }
                            keyValuePairList.Add(new KeyValuePair <AssociationEndMember, AssociationEndMember>(associationEndMember2, associationEndMember1));
                        }
                    }
                }
            }
            return(keyValuePairList);
        }
        internal static bool TryRewrite(
            DbQueryCommandTree tree,
            Span span,
            MergeOption mergeOption,
            AliasGenerator aliasGenerator,
            out DbExpression newQuery,
            out SpanIndex spanInfo)
        {
            newQuery = (DbExpression)null;
            spanInfo = (SpanIndex)null;
            ObjectSpanRewriter objectSpanRewriter = (ObjectSpanRewriter)null;
            bool flag = Span.RequiresRelationshipSpan(mergeOption);

            if (span != null && span.SpanList.Count > 0)
            {
                objectSpanRewriter = (ObjectSpanRewriter) new ObjectFullSpanRewriter((DbCommandTree)tree, tree.Query, span, aliasGenerator);
            }
            else if (flag)
            {
                objectSpanRewriter = new ObjectSpanRewriter((DbCommandTree)tree, tree.Query, aliasGenerator);
            }
            if (objectSpanRewriter != null)
            {
                objectSpanRewriter.RelationshipSpan = flag;
                newQuery = objectSpanRewriter.RewriteQuery();
                if (newQuery != null)
                {
                    spanInfo = objectSpanRewriter.SpanIndex;
                }
            }
            return(spanInfo != null);
        }
        public virtual ObjectQueryExecutionPlan Prepare(
            ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Span span,
            IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > compiledQueryParameters, AliasGenerator aliasGenerator)
        {
            var treeResultType = tree.Query.ResultType;

            // Rewrite this tree for Span?
            DbExpression spannedQuery = null;
            SpanIndex    spanInfo;

            if (ObjectSpanRewriter.TryRewrite(tree, span, mergeOption, aliasGenerator, out spannedQuery, out spanInfo))
            {
                tree = DbQueryCommandTree.FromValidExpression(tree.MetadataWorkspace, tree.DataSpace, spannedQuery);
            }
            else
            {
                spanInfo = null;
            }

            var entityDefinition = CreateCommandDefinition(context, tree);

            var cacheManager = context.Perspective.MetadataWorkspace.GetQueryCacheManager();

            var shaperFactory = Translator.TranslateColumnMap(
                _translator,
                elementType, cacheManager, entityDefinition.CreateColumnMap(null),
                context.MetadataWorkspace, spanInfo, mergeOption, false);

            // attempt to determine entity information for this query (e.g. which entity type and which entity set)

            EntitySet singleEntitySet = null;

            // determine if the entity set is unambiguous given the entity type
            if (treeResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType &&
                entityDefinition.EntitySets != null)
            {
                foreach (var entitySet in entityDefinition.EntitySets)
                {
                    if (entitySet != null &&
                        entitySet.ElementType.IsAssignableFrom(((CollectionType)treeResultType.EdmType).TypeUsage.EdmType))
                    {
                        if (singleEntitySet == null)
                        {
                            // found a single match
                            singleEntitySet = entitySet;
                        }
                        else
                        {
                            // there's more than one matching entity set
                            singleEntitySet = null;
                            break;
                        }
                    }
                }
            }

            return(new ObjectQueryExecutionPlan(
                       entityDefinition, shaperFactory, treeResultType, mergeOption, singleEntitySet, compiledQueryParameters));
        }
        public virtual ObjectQueryExecutionPlan Prepare(
            ObjectContext context,
            DbQueryCommandTree tree,
            Type elementType,
            MergeOption mergeOption,
            bool streaming,
            Span span,
            IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > compiledQueryParameters,
            AliasGenerator aliasGenerator)
        {
            TypeUsage    resultType = tree.Query.ResultType;
            DbExpression newQuery;
            SpanIndex    spanInfo;

            if (ObjectSpanRewriter.TryRewrite(tree, span, mergeOption, aliasGenerator, out newQuery, out spanInfo))
            {
                tree = DbQueryCommandTree.FromValidExpression(tree.MetadataWorkspace, tree.DataSpace, newQuery, tree.UseDatabaseNullSemantics);
            }
            else
            {
                spanInfo = (SpanIndex)null;
            }
            EntityCommandDefinition commandDefinition   = ObjectQueryExecutionPlanFactory.CreateCommandDefinition(context, tree);
            ShaperFactory           resultShaperFactory = System.Data.Entity.Core.Common.Internal.Materialization.Translator.TranslateColumnMap(this._translator, elementType, commandDefinition.CreateColumnMap((DbDataReader)null), context.MetadataWorkspace, spanInfo, mergeOption, streaming, false);
            EntitySet singleEntitySet = (EntitySet)null;

            if (resultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType && commandDefinition.EntitySets != null)
            {
                foreach (EntitySet entitySet in commandDefinition.EntitySets)
                {
                    if (entitySet != null && entitySet.ElementType.IsAssignableFrom(((CollectionType)resultType.EdmType).TypeUsage.EdmType))
                    {
                        if (singleEntitySet == null)
                        {
                            singleEntitySet = entitySet;
                        }
                        else
                        {
                            singleEntitySet = (EntitySet)null;
                            break;
                        }
                    }
                }
            }
            return(new ObjectQueryExecutionPlan((DbCommandDefinition)commandDefinition, resultShaperFactory, resultType, mergeOption, streaming, singleEntitySet, compiledQueryParameters));
        }
        private static bool IsValidRelationshipSpan(
            EntityType compareType,
            AssociationType associationType,
            AssociationEndMember fromEnd,
            AssociationEndMember toEnd)
        {
            if (associationType.IsForeignKey || RelationshipMultiplicity.One != toEnd.RelationshipMultiplicity && toEnd.RelationshipMultiplicity != RelationshipMultiplicity.ZeroOrOne)
            {
                return(false);
            }
            EntityType elementType = (EntityType)((RefType)fromEnd.TypeUsage.EdmType).ElementType;

            if (!ObjectSpanRewriter.EntityTypeEquals((EntityTypeBase)compareType, (EntityTypeBase)elementType) && !TypeSemantics.IsSubTypeOf((EdmType)compareType, (EdmType)elementType))
            {
                return(TypeSemantics.IsSubTypeOf((EdmType)elementType, (EdmType)compareType));
            }
            return(true);
        }
        internal static bool TryRewrite(
            DbQueryCommandTree tree, Span span, MergeOption mergeOption, AliasGenerator aliasGenerator, out DbExpression newQuery,
            out SpanIndex spanInfo)
        {
            newQuery = null;
            spanInfo = null;

            ObjectSpanRewriter rewriter  = null;
            var requiresRelationshipSpan = Span.RequiresRelationshipSpan(mergeOption);

            // Potentially perform a rewrite for span.
            // Note that the public 'Span' property is NOT used to retrieve the Span instance
            // since this forces creation of a Span object that may not be required.
            if (span != null &&
                span.SpanList.Count > 0)
            {
                rewriter = new ObjectFullSpanRewriter(tree, tree.Query, span, aliasGenerator);
            }
            else if (requiresRelationshipSpan)
            {
                rewriter = new ObjectSpanRewriter(tree, tree.Query, aliasGenerator);
            }

            if (rewriter != null)
            {
                rewriter.RelationshipSpan = requiresRelationshipSpan;
                newQuery = rewriter.RewriteQuery();
                if (newQuery != null)
                {
                    Debug.Assert(
                        rewriter.SpanIndex != null || tree.Query.ResultType.EdmEquals(newQuery.ResultType),
                        "Query was rewritten for Span but no SpanIndex was created?");
                    spanInfo = rewriter.SpanIndex;
                }
            }

            return(spanInfo != null);
        }
        internal static bool TryRewrite(
            DbQueryCommandTree tree, Span span, MergeOption mergeOption, AliasGenerator aliasGenerator, out DbExpression newQuery,
            out SpanIndex spanInfo)
        {
            newQuery = null;
            spanInfo = null;

            ObjectSpanRewriter rewriter = null;
            var requiresRelationshipSpan = Span.RequiresRelationshipSpan(mergeOption);

            // Potentially perform a rewrite for span.
            // Note that the public 'Span' property is NOT used to retrieve the Span instance
            // since this forces creation of a Span object that may not be required.
            if (span != null
                && span.SpanList.Count > 0)
            {
                rewriter = new ObjectFullSpanRewriter(tree, tree.Query, span, aliasGenerator);
            }
            else if (requiresRelationshipSpan)
            {
                rewriter = new ObjectSpanRewriter(tree, tree.Query, aliasGenerator);
            }

            if (rewriter != null)
            {
                rewriter.RelationshipSpan = requiresRelationshipSpan;
                newQuery = rewriter.RewriteQuery();
                if (newQuery != null)
                {
                    Debug.Assert(
                        rewriter.SpanIndex != null || tree.Query.ResultType.EdmEquals(newQuery.ResultType),
                        "Query was rewritten for Span but no SpanIndex was created?");
                    spanInfo = rewriter.SpanIndex;
                }
            }

            return (spanInfo != null);
        }