예제 #1
0
        // --------------------
        // Internal Constructors
        // --------------------

        /// <summary>
        ///     The common constructor.
        /// </summary>
        /// <param name="queryState"> The underlying implementation of this ObjectQuery </param>
        /// <returns> A new ObjectQuery instance. </returns>
        internal ObjectQuery(ObjectQueryState queryState)
        {
            DebugCheck.NotNull(queryState);

            // Set the query state.
            _state = queryState;
        }
예제 #2
0
        // --------------------
        // Internal Constructors
        // --------------------

        /// <summary>
        ///   The common constructor.
        /// </summary>
        /// <param name="queryState">
        ///   The underlying implementation of this ObjectQuery
        /// </param>
        /// <returns>
        ///   A new ObjectQuery instance.
        /// </returns>
        internal ObjectQuery(ObjectQueryState queryState)
        {
            Debug.Assert(queryState != null, "ObjectQuery state cannot be null");

            // Set the query state.
            _state = queryState;
        }
        // --------------------
        // Internal Constructors
        // --------------------

        /// <summary>
        ///   The common constructor.
        /// </summary>
        /// <param name="queryState">
        ///   The underlying implementation of this ObjectQuery
        /// </param>
        /// <returns>
        ///   A new ObjectQuery instance.
        /// </returns>
        internal ObjectQuery(ObjectQueryState queryState)
        {
            Debug.Assert(queryState != null, "ObjectQuery state cannot be null");

            // Set the query state.
            this._state = queryState;
        }
예제 #4
0
        // --------------------
        // Internal Constructors
        // --------------------

        // <summary>
        // The common constructor.
        // </summary>
        // <param name="queryState"> The underlying implementation of this ObjectQuery </param>
        // <returns> A new ObjectQuery instance. </returns>
        internal ObjectQuery(ObjectQueryState queryState)
        {
            DebugCheck.NotNull(queryState);

            // Set the query state.
            _state = queryState;
        }
        internal override ObjectQueryState Include <TElementType>(
            ObjectQuery <TElementType> sourceQuery,
            string includePath)
        {
            ObjectQueryState other = (ObjectQueryState) new EntitySqlQueryState(this.ElementType, this._queryText, this._queryExpression, this._allowsLimit, this.ObjectContext, ObjectParameterCollection.DeepCopy(this.Parameters), Span.IncludeIn(this.Span, includePath), (ObjectQueryExecutionPlanFactory)null);

            this.ApplySettingsTo(other);
            return(other);
        }
        internal override ObjectQueryState Include <TElementType>(
            ObjectQuery <TElementType> sourceQuery,
            string includePath)
        {
            MethodInfo       includeMethod = ELinqQueryState.GetIncludeMethod <TElementType>(sourceQuery);
            ObjectQueryState other         = (ObjectQueryState) new ELinqQueryState(this.ElementType, this.ObjectContext, (Expression)Expression.Call((Expression)Expression.Constant((object)sourceQuery), includeMethod, (Expression)Expression.Constant((object)includePath, typeof(string))), (ObjectQueryExecutionPlanFactory)null);

            this.ApplySettingsTo(other);
            return(other);
        }
        /// <summary>
        /// Helper method to extract the Entity-SQL command text from an <see cref="ObjectQueryState"/> instance if that
        /// instance models an Entity-SQL-backed ObjectQuery, or to throw an exception indicating that query builder methods
        /// are not supported on this query.
        /// </summary>
        /// <param name="query">The instance from which the Entity-SQL command text should be retrieved</param>
        /// <returns>The Entity-SQL command text, if the specified query state instance is based on Entity-SQL</returns>
        /// <exception cref="NotSupportedException">
        ///     If the specified instance is not based on Entity-SQL command text, and so does not support Entity-SQL query builder methods
        /// </exception>
        private static string GetCommandText(ObjectQueryState query)
        {
            string commandText = null;
            if (!query.TryGetCommandText(out commandText))
            {
                throw new NotSupportedException(Strings.ObjectQuery_QueryBuilder_NotSupportedLinqSource);
            }

            return commandText;
        }
        /// <summary>
        /// Helper method to extract the Entity-SQL command text from an <see cref="ObjectQueryState"/> instance if that
        /// instance models an Entity-SQL-backed ObjectQuery, or to throw an exception indicating that query builder methods
        /// are not supported on this query.
        /// </summary>
        /// <param name="query">The instance from which the Entity-SQL command text should be retrieved</param>
        /// <returns>The Entity-SQL command text, if the specified query state instance is based on Entity-SQL</returns>
        /// <exception cref="NotSupportedException">
        ///     If the specified instance is not based on Entity-SQL command text, and so does not support Entity-SQL query builder methods
        /// </exception>
        private static string GetCommandText(ObjectQueryState query)
        {
            string commandText = null;
            if(!query.TryGetCommandText(out commandText))
            {
                throw EntityUtil.NotSupported(System.Data.Entity.Strings.ObjectQuery_QueryBuilder_NotSupportedLinqSource);
            }

            return commandText;
        }
        internal override ObjectQueryExecutionPlan GetExecutionPlan(
            MergeOption?forMergeOption)
        {
            MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption);
            ObjectQueryExecutionPlan queryExecutionPlan1 = this._cachedPlan;

            if (queryExecutionPlan1 != null)
            {
                if (queryExecutionPlan1.MergeOption == mergeOption && queryExecutionPlan1.Streaming == this.EffectiveStreamingBehavior)
                {
                    return(queryExecutionPlan1);
                }
                queryExecutionPlan1 = (ObjectQueryExecutionPlan)null;
            }
            QueryCacheManager      queryCacheManager = (QueryCacheManager)null;
            EntitySqlQueryCacheKey key = (EntitySqlQueryCacheKey)null;

            if (this.PlanCachingEnabled)
            {
                key = new EntitySqlQueryCacheKey(this.ObjectContext.DefaultContainerName, this._queryText, this.Parameters == null ? 0 : this.Parameters.Count, this.Parameters == null ? (string)null : this.Parameters.GetCacheKey(), this.Span == null ? (string)null : this.Span.GetCacheKey(), mergeOption, this.EffectiveStreamingBehavior, this.ElementType);
                queryCacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                ObjectQueryExecutionPlan queryExecutionPlan2 = (ObjectQueryExecutionPlan)null;
                if (queryCacheManager.TryCacheLookup <EntitySqlQueryCacheKey, ObjectQueryExecutionPlan>(key, out queryExecutionPlan2))
                {
                    queryExecutionPlan1 = queryExecutionPlan2;
                }
            }
            if (queryExecutionPlan1 == null)
            {
                queryExecutionPlan1 = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, this.Parse(), true), this.ElementType, mergeOption, this.EffectiveStreamingBehavior, this.Span, (IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> >)null, DbExpressionBuilder.AliasGenerator);
                if (key != null)
                {
                    QueryCacheEntry inQueryCacheEntry  = new QueryCacheEntry((QueryCacheKey)key, (object)queryExecutionPlan1);
                    QueryCacheEntry outQueryCacheEntry = (QueryCacheEntry)null;
                    if (queryCacheManager.TryLookupAndAdd(inQueryCacheEntry, out outQueryCacheEntry))
                    {
                        queryExecutionPlan1 = (ObjectQueryExecutionPlan)outQueryCacheEntry.GetTarget();
                    }
                }
            }
            if (this.Parameters != null)
            {
                this.Parameters.SetReadOnly(true);
            }
            this._cachedPlan = queryExecutionPlan1;
            return(queryExecutionPlan1);
        }
 internal static ObjectQueryState Where(ObjectQueryState query, string alias, string predicate, ObjectParameter[] parameters)
 {
     return BuildOrderByOrWhere(query, alias, predicate, parameters, _whereOp, null, false);
 }
 internal static ObjectQueryState UnionAll(ObjectQueryState leftQuery, ObjectQueryState rightQuery)
 {
     // Ensure the Spans of the query arguments are merged into the new query's Span.
     Span newSpan = Span.CopyUnion(leftQuery.Span, rightQuery.Span);
     // Call the SetOp helper.
     return BuildSetOp(leftQuery, rightQuery, newSpan, _unionAllOp);
 }
        internal static ObjectQueryState Top(ObjectQueryState query, string alias, string count, ObjectParameter[] parameters)
        {
            int queryLength = count.Length;
            string queryText = GetCommandText(query);
            bool limitAllowed = ((EntitySqlQueryState)query).AllowsLimitSubclause;

            if (limitAllowed)
            {
                // Build the new query string:
                // <this query> LIMIT <count>
                queryLength += (queryText.Length +
                                _limitOp.Length
                    // + count.Length is added above
                                );
            }
            else
            {
                // Build the new query string:
                // "SELECT VALUE TOP(<count>) <alias> FROM (<this query>) AS <alias>"
                queryLength += (_topOp.Length +
                    // count.Length + is added above
                               _topInfix.Length +
                               alias.Length +
                               _fromOp.Length +
                               queryText.Length +
                               _asOp.Length +
                               alias.Length);
            }

            StringBuilder builder = new StringBuilder(queryLength);
            if (limitAllowed)
            {
                builder.Append(queryText);
                builder.Append(_limitOp);
                builder.Append(count);
            }
            else
            {
                builder.Append(_topOp);
                builder.Append(count);
                builder.Append(_topInfix);
                builder.Append(alias);
                builder.Append(_fromOp);
                builder.Append(queryText);
                builder.Append(_asOp);
                builder.Append(alias);
            }

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed.
            return NewBuilderQuery(query, query.ElementType, builder, query.Span, MergeParameters(query.ObjectContext, query.Parameters, parameters));
        }
 internal static ObjectQueryState Skip(ObjectQueryState query, string alias, string keys, string count, ObjectParameter[] parameters)
 {
     Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(count), "Invalid skip count");
     return BuildOrderByOrWhere(query, alias, keys, parameters, _orderByOp, count, true);
 }
 internal static ObjectQueryState SelectValue(ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters, Type projectedType)
 {
     return BuildSelectOrSelectValue(query, alias, projection, parameters, _selectValueOp, projectedType);
 }
 internal static ObjectQueryState Select(ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters)
 {
     return BuildSelectOrSelectValue(query, alias, projection, parameters, _selectOp, typeof(DbDataRecord));
 }
 private static ObjectQueryState NewBuilderQuery(ObjectQueryState sourceQuery, Type elementType, StringBuilder queryText, Span newSpan, IEnumerable<ObjectParameter> enumerableParams)
 {
     return NewBuilderQuery(sourceQuery, elementType, queryText, false, newSpan, enumerableParams);
 }
예제 #17
0
 internal ObjectQuery(ObjectQueryState queryState)
     : base(queryState)
 {
 }
 internal static ObjectQueryState Except(ObjectQueryState leftQuery, ObjectQueryState rightQuery)
 {
     // Call the SetOp helper.
     // Span is taken from the leftmost query.
     return EntitySqlQueryBuilder.BuildSetOp(leftQuery, rightQuery, leftQuery.Span, _exceptOp);
 }
        internal override ObjectQueryExecutionPlan GetExecutionPlan(
            MergeOption?forMergeOption)
        {
            ObjectQueryExecutionPlan queryExecutionPlan1 = this._cachedPlan;

            if (queryExecutionPlan1 != null)
            {
                MergeOption?mergeOption = ObjectQueryState.GetMergeOption(forMergeOption, this.UserSpecifiedMergeOption);
                if (mergeOption.HasValue && mergeOption.Value != queryExecutionPlan1.MergeOption || (this._recompileRequired() || this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior != this._useCSharpNullComparisonBehavior))
                {
                    queryExecutionPlan1 = (ObjectQueryExecutionPlan)null;
                }
            }
            if (queryExecutionPlan1 == null)
            {
                this._recompileRequired = (Func <bool>)null;
                this.ResetParameters();
                ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                DbExpression        dbExpression        = expressionConverter.Convert();
                this._recompileRequired = expressionConverter.RecompileRequired;
                MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, expressionConverter.PropagatedMergeOption);
                this._useCSharpNullComparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;
                this._linqParameters = expressionConverter.GetParameters();
                if (this._linqParameters != null && this._linqParameters.Any <Tuple <ObjectParameter, QueryParameterExpression> >())
                {
                    ObjectParameterCollection parameterCollection = this.EnsureParameters();
                    parameterCollection.SetReadOnly(false);
                    foreach (Tuple <ObjectParameter, QueryParameterExpression> linqParameter in this._linqParameters)
                    {
                        ObjectParameter objectParameter = linqParameter.Item1;
                        parameterCollection.Add(objectParameter);
                    }
                    parameterCollection.SetReadOnly(true);
                }
                QueryCacheManager queryCacheManager = (QueryCacheManager)null;
                LinqQueryCacheKey key1 = (LinqQueryCacheKey)null;
                string            key2;
                if (this.PlanCachingEnabled && !this._recompileRequired() && ExpressionKeyGen.TryGenerateKey(dbExpression, out key2))
                {
                    key1 = new LinqQueryCacheKey(key2, this.Parameters == null ? 0 : this.Parameters.Count, this.Parameters == null ? (string)null : this.Parameters.GetCacheKey(), expressionConverter.PropagatedSpan == null ? (string)null : expressionConverter.PropagatedSpan.GetCacheKey(), mergeOption, this.EffectiveStreamingBehavior, this._useCSharpNullComparisonBehavior, this.ElementType);
                    queryCacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                    ObjectQueryExecutionPlan queryExecutionPlan2 = (ObjectQueryExecutionPlan)null;
                    if (queryCacheManager.TryCacheLookup <LinqQueryCacheKey, ObjectQueryExecutionPlan>(key1, out queryExecutionPlan2))
                    {
                        queryExecutionPlan1 = queryExecutionPlan2;
                    }
                }
                if (queryExecutionPlan1 == null)
                {
                    queryExecutionPlan1 = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, dbExpression, !this._useCSharpNullComparisonBehavior), this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, (IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> >)null, expressionConverter.AliasGenerator);
                    if (key1 != null)
                    {
                        QueryCacheEntry inQueryCacheEntry  = new QueryCacheEntry((QueryCacheKey)key1, (object)queryExecutionPlan1);
                        QueryCacheEntry outQueryCacheEntry = (QueryCacheEntry)null;
                        if (queryCacheManager.TryLookupAndAdd(inQueryCacheEntry, out outQueryCacheEntry))
                        {
                            queryExecutionPlan1 = (ObjectQueryExecutionPlan)outQueryCacheEntry.GetTarget();
                        }
                    }
                }
                this._cachedPlan = queryExecutionPlan1;
            }
            if (this._linqParameters != null)
            {
                foreach (Tuple <ObjectParameter, QueryParameterExpression> linqParameter in this._linqParameters)
                {
                    ObjectParameter          objectParameter     = linqParameter.Item1;
                    QueryParameterExpression parameterExpression = linqParameter.Item2;
                    if (parameterExpression != null)
                    {
                        objectParameter.Value = parameterExpression.EvaluateParameter((object[])null);
                    }
                }
            }
            return(queryExecutionPlan1);
        }
        internal static ObjectQueryState Distinct(ObjectQueryState query)
        {
            // Build the new query string - "SET(<this query>)"
            string queryText = GetCommandText(query);
            StringBuilder builder = new StringBuilder(_distinctProlog.Length + queryText.Length + _distinctEpilog.Length);
            builder.Append(_distinctProlog);
            builder.Append(queryText);
            builder.Append(_distinctEpilog);

            // Span is carried over, no adjustment is needed

            return NewBuilderQuery(query, query.ElementType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters));
        }
        private static ObjectQueryState BuildOrderByOrWhere(ObjectQueryState query, string alias, string predicateOrKeys, ObjectParameter[] parameters, string op, string skipCount, bool allowsLimit)
        {
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(alias), "Invalid alias");
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(predicateOrKeys), "Invalid predicate/keys");
            Debug.Assert(null == skipCount || op == _orderByOp, "Skip clause used with WHERE operator?");

            string queryText = GetCommandText(query);

            // Build the new query string:
            // Either: "SELECT VALUE <alias> FROM (<this query>) AS <alias> WHERE <predicate>"
            //  (for Where)
            // Or:  "SELECT VALUE <alias> FROM (<this query>) AS <alias> ORDER BY <keys> <optional: SKIP <skip>>"
            // Depending on the value of 'op'
            int queryLength = _selectValueOp.Length +
                              alias.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length +
                              op.Length +
                              predicateOrKeys.Length;
            
            if (skipCount != null)
            {
                queryLength += (_skipOp.Length + skipCount.Length);
            }

            StringBuilder builder = new StringBuilder(queryLength);
            builder.Append(_selectValueOp);
            builder.Append(alias);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);
            builder.Append(op);
            builder.Append(predicateOrKeys);
            if (skipCount != null)
            {
                builder.Append(_skipOp);
                builder.Append(skipCount);
            }

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed.
            return NewBuilderQuery(query, query.ElementType, builder, allowsLimit, query.Span, MergeParameters(query.ObjectContext, query.Parameters,  parameters));
        }
        private static ObjectQueryState BuildSelectOrSelectValue(ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters, string projectOp, Type elementType)
        {
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(alias), "Invalid alias");
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(projection), "Invalid projection");

            string queryText = GetCommandText(query);

            // Build the new query string - "<project op> <projection> FROM (<this query>) AS <alias>"
            int queryLength = projectOp.Length +
                              projection.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length;

            StringBuilder builder = new StringBuilder(queryLength);
            builder.Append(projectOp);
            builder.Append(projection);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span should not be carried over from a Select or SelectValue operation.
            return NewBuilderQuery(query, elementType, builder, null, MergeParameters(query.ObjectContext, query.Parameters, parameters));
        }
        // SetOp helper - note that this doesn't merge Spans, since Except uses the original query's Span
        // while Intersect/Union/UnionAll use the merged Span.
        private static ObjectQueryState BuildSetOp(ObjectQueryState leftQuery, ObjectQueryState rightQuery, Span newSpan, string setOp)
        {
            // Assert that the arguments aren't null (should have been verified by ObjectQuery)
            Debug.Assert(leftQuery != null, "Left query is null?");
            Debug.Assert(rightQuery != null, "Right query is null?");
            Debug.Assert(leftQuery.ElementType.Equals(rightQuery.ElementType), "Incompatible element types in arguments to Except<T>/Intersect<T>/Union<T>/UnionAll<T>?");

            // Retrieve the left and right arguments to the set operation - 
            // this will throw if either input query is not an Entity-SQL query.
            string left = GetCommandText(leftQuery);
            string right = GetCommandText(rightQuery);
                        
            // ObjectQuery arguments must be associated with the same ObjectContext instance as the implemented query
            if (!object.ReferenceEquals(leftQuery.ObjectContext, rightQuery.ObjectContext))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.ObjectQuery_QueryBuilder_InvalidQueryArgument, "query"); 
            }
                                    
            // Create a string builder only large enough to contain the new query text
            int queryLength = _setOpProlog.Length + left.Length + setOp.Length + right.Length + _setOpEpilog.Length;
            StringBuilder builder = new StringBuilder(queryLength);

            // Build the new query
            builder.Append(_setOpProlog);
            builder.Append(left);
            builder.Append(setOp);
            builder.Append(right);
            builder.Append(_setOpEpilog);

            // Create a new query implementation and apply the state of this implementation to it.
            // The Span of the query argument will be merged into the new query's Span by the caller, iff the Set Op is NOT Except.
            // See the Except, Intersect, Union and UnionAll methods in this class for examples.
            return NewBuilderQuery(leftQuery, leftQuery.ElementType, builder, newSpan, MergeParameters(leftQuery.Parameters, rightQuery.Parameters));
        }
        private static ObjectQueryState NewBuilderQuery(ObjectQueryState sourceQuery, Type elementType, StringBuilder queryText, bool allowsLimit, Span newSpan, IEnumerable<ObjectParameter> enumerableParams)
        {
            ObjectParameterCollection queryParams = enumerableParams as ObjectParameterCollection;
            if (queryParams == null && enumerableParams != null)
            {
                queryParams = new ObjectParameterCollection(sourceQuery.ObjectContext.Perspective);
                foreach (ObjectParameter objectParam in enumerableParams)
                {
                    queryParams.Add(objectParam);
                }
            }

            EntitySqlQueryState newState = new EntitySqlQueryState(elementType, queryText.ToString(), allowsLimit, sourceQuery.ObjectContext, queryParams, newSpan);
            
            sourceQuery.ApplySettingsTo(newState);
            
            return newState;
        }
예제 #25
0
        internal override ObjectQueryExecutionPlan GetExecutionPlan(
            MergeOption?forMergeOption)
        {
            ObjectQueryExecutionPlan queryExecutionPlan      = (ObjectQueryExecutionPlan)null;
            CompiledQueryCacheEntry  compiledQueryCacheEntry = this._cacheEntry;
            bool comparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;

            if (compiledQueryCacheEntry != null)
            {
                MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                if (queryExecutionPlan == null)
                {
                    ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                    DbExpression        query = expressionConverter.Convert();
                    IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > parameters = expressionConverter.GetParameters();
                    ObjectQueryExecutionPlan newPlan = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, query, !comparisonBehavior), this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, parameters, expressionConverter.AliasGenerator);
                    queryExecutionPlan = compiledQueryCacheEntry.SetExecutionPlan(newPlan, comparisonBehavior);
                }
            }
            else
            {
                QueryCacheManager     queryCacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                CompiledQueryCacheKey key = new CompiledQueryCacheKey(this._cacheToken);
                if (queryCacheManager.TryCacheLookup <CompiledQueryCacheKey, CompiledQueryCacheEntry>(key, out compiledQueryCacheEntry))
                {
                    this._cacheEntry = compiledQueryCacheEntry;
                    MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                    queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                }
                if (queryExecutionPlan == null)
                {
                    ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                    DbExpression        query = expressionConverter.Convert();
                    IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > parameters = expressionConverter.GetParameters();
                    DbQueryCommandTree tree = DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, query, !comparisonBehavior);
                    if (compiledQueryCacheEntry == null)
                    {
                        compiledQueryCacheEntry = new CompiledQueryCacheEntry((QueryCacheKey)key, expressionConverter.PropagatedMergeOption);
                        QueryCacheEntry outQueryCacheEntry;
                        if (queryCacheManager.TryLookupAndAdd((QueryCacheEntry)compiledQueryCacheEntry, out outQueryCacheEntry))
                        {
                            compiledQueryCacheEntry = (CompiledQueryCacheEntry)outQueryCacheEntry;
                        }
                        this._cacheEntry = compiledQueryCacheEntry;
                    }
                    MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                    queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                    if (queryExecutionPlan == null)
                    {
                        ObjectQueryExecutionPlan newPlan = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, parameters, expressionConverter.AliasGenerator);
                        queryExecutionPlan = compiledQueryCacheEntry.SetExecutionPlan(newPlan, comparisonBehavior);
                    }
                }
            }
            ObjectParameterCollection parameterCollection = this.EnsureParameters();

            if (queryExecutionPlan.CompiledQueryParameters != null && queryExecutionPlan.CompiledQueryParameters.Any <Tuple <ObjectParameter, QueryParameterExpression> >())
            {
                parameterCollection.SetReadOnly(false);
                parameterCollection.Clear();
                foreach (Tuple <ObjectParameter, QueryParameterExpression> compiledQueryParameter in queryExecutionPlan.CompiledQueryParameters)
                {
                    ObjectParameter          objectParameter     = compiledQueryParameter.Item1.ShallowCopy();
                    QueryParameterExpression parameterExpression = compiledQueryParameter.Item2;
                    parameterCollection.Add(objectParameter);
                    if (parameterExpression != null)
                    {
                        objectParameter.Value = parameterExpression.EvaluateParameter(this._parameterValues);
                    }
                }
            }
            parameterCollection.SetReadOnly(true);
            return(queryExecutionPlan);
        }
        internal static ObjectQueryState OfType(ObjectQueryState query, EdmType newType, Type clrOfType)
        {
            Debug.Assert(newType != null, "OfType cannot be null");
            Debug.Assert(Helper.IsEntityType(newType) || Helper.IsComplexType(newType), "OfType must be Entity or Complex type");

            string queryText = GetCommandText(query);

            // Build the new query string - "OFTYPE((<query>), [<type namespace>].[<type name>])"
            int queryLength = _ofTypeProlog.Length +
                              queryText.Length +
                              _ofTypeInfix.Length +
                              newType.NamespaceName.Length +
                              (newType.NamespaceName != string.Empty ? _ofTypeInfix2.Length : 0) +
                              newType.Name.Length +
                              _ofTypeEpilog.Length;

            StringBuilder builder = new StringBuilder(queryLength);
            builder.Append(_ofTypeProlog);
            builder.Append(queryText);
            builder.Append(_ofTypeInfix);
            if (newType.NamespaceName != string.Empty)
            {
                builder.Append(newType.NamespaceName);
                builder.Append(_ofTypeInfix2);
            }
            builder.Append(newType.Name);
            builder.Append(_ofTypeEpilog);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed
            return NewBuilderQuery(query, clrOfType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters));
        }
 internal static ObjectQueryState OrderBy(ObjectQueryState query, string alias, string keys, ObjectParameter[] parameters)
 {
     return BuildOrderByOrWhere(query, alias, keys, parameters, _orderByOp, null, true);
 }
 internal ObjectQuery(ObjectQueryState queryState)
 {
     this._state = queryState;
 }
        internal static ObjectQueryState GroupBy(ObjectQueryState query, string alias, string keys, string projection, ObjectParameter[] parameters)
        {
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(alias), "Invalid alias");
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(alias), "Invalid keys");
            Debug.Assert(!StringUtil.IsNullOrEmptyOrWhiteSpace(projection), "Invalid projection");

            string queryText = GetCommandText(query);

            // Build the new query string:
            // "SELECT <projection> FROM (<this query>) AS <alias> GROUP BY <keys>"
            int queryLength = _selectOp.Length +
                              projection.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length +
                              _groupByOp.Length +
                              keys.Length;

            StringBuilder builder = new StringBuilder(queryLength);
            builder.Append(_selectOp);
            builder.Append(projection);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);
            builder.Append(_groupByOp);
            builder.Append(keys);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span should not be carried over from a GroupBy operation.
            return NewBuilderQuery(query, typeof(DbDataRecord), builder, null, MergeParameters(query.ObjectContext, query.Parameters, parameters));
        }
        internal static ObjectQueryState Skip(ObjectQueryState query, string alias, string keys, string count, ObjectParameter[] parameters)
        {
            DebugCheck.NotEmpty(count);

            return BuildOrderByOrWhere(query, alias, keys, parameters, _orderByOp, count, true);
        }