예제 #1
0
		/// <summary>
		/// Called from select when a physical query has been done
		/// </summary>
		/// <param name="Fields"></param>
		/// <param name="From_TableName"></param>
		/// <param name="Where_NameCondValue"></param>
		/// <param name="dt"></param>
		private void QueryCacheSet(string[] Fields, string From_TableName, object[,] Where_NameCondValue,DataTable dt)
		{
			lock(QueryCache)
			{
				if(QueryCache.Count>=QueryCacheMaxLen)
					QueryCache.RemoveAt(0);
				QueryCacheEntry q = new QueryCacheEntry();
				q.Fields=Fields;
				q.From_TableName=From_TableName;
				q.Where_NameCondValue=Where_NameCondValue;
				q.dt=dt;
				QueryCache.Add(q);
			}
		}
        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);
        }
        /// <summary>
        /// Gets an entitycommanddefinition from cache if a match is found for the given cache key.
        /// </summary>
        /// <param name="entityCommandDefinition">out param. returns the entitycommanddefinition for a given cache key</param>
        /// <returns>true if a match is found in cache, false otherwise</returns>
        private bool TryGetEntityCommandDefinitionFromQueryCache(out EntityCommandDefinition entityCommandDefinition)
        {
            Debug.Assert(null != _connection, "Connection must not be null at this point");
            entityCommandDefinition = null;

            //
            // if EnableQueryCaching is false, then just return to force the CommandDefinition to be created
            //
            if (!this._enableQueryPlanCaching || string.IsNullOrEmpty(this._esqlCommandText))
            {
                return(false);
            }

            //
            // Create cache key
            //
            EntityClientCacheKey queryCacheKey = new EntityClientCacheKey(this);

            //
            // Try cache lookup
            //
            QueryCacheManager queryCacheManager = _connection.GetMetadataWorkspace().GetQueryCacheManager();

            Debug.Assert(null != queryCacheManager, "QuerycacheManager instance cannot be null");
            if (!queryCacheManager.TryCacheLookup(queryCacheKey, out entityCommandDefinition))
            {
                //
                // if not, construct the command definition using no special options;
                //
                entityCommandDefinition = CreateCommandDefinition();

                //
                // add to the cache
                //
                QueryCacheEntry outQueryCacheEntry = null;
                if (queryCacheManager.TryLookupAndAdd(new QueryCacheEntry(queryCacheKey, entityCommandDefinition), out outQueryCacheEntry))
                {
                    entityCommandDefinition = (EntityCommandDefinition)outQueryCacheEntry.GetTarget();
                }
            }

            Debug.Assert(null != entityCommandDefinition, "out entityCommandDefinition must not be null");

            return(true);
        }
예제 #4
0
		/// <summary>
		/// Called from select when a physical query has been done
		/// </summary>
		/// <param name="Fields"></param>
		/// <param name="From_TableName"></param>
		/// <param name="Where_NameCondValue"></param>
		/// <param name="dt"></param>
		private void QueryCacheSet(string[] Fields, string From_TableName, object[,] Where_NameCondValue,DataTable2 dt)
		{
			lock(QueryCache)
			{
				if(QueryCache.Count>=QueryCacheMaxLen)
					QueryCache.RemoveAt(0);
				QueryCacheEntry q = new QueryCacheEntry();
				q.Fields=(string[])Fields.Clone();
				q.From_TableName=From_TableName;
				q.Where_NameCondValue= new object[Where_NameCondValue.GetLength(0),3];
				for(int n=0;n<Where_NameCondValue.GetLength(0);n++)
				{
					q.Where_NameCondValue[n,0]=Where_NameCondValue[n,0];
					q.Where_NameCondValue[n,1]=Where_NameCondValue[n,1];
					q.Where_NameCondValue[n,2]=Where_NameCondValue[n,2];
				}
				q.dt=dt;
				QueryCache.Add(q);
			}
		}
        private QueryCacheEntry QueryAsyncToCache(QueryQueueEntry key)
        {
            if (!Database.IsOpen)
            {
                return(null);
            }

            try
            {
                var data = new QueryCacheEntry(null, null);

                var scores = key.QueryEval
                    ? Task.Run(() => GetChessdbcnScores(key.CurrentFen))
                    : Task.FromResult(new Dictionary <Move, ChessDBCNScore>());

                if (key.San == San.NullMove)
                {
                    data.Stats  = Database.Query(key.QueryFen);
                    data.Scores = scores.Result;
                    lock (QueryCacheLock)
                    {
                        QueryCache.Add(key, data);
                    }
                }
                else
                {
                    data.Stats  = Database.Query(key.QueryFen, key.San);
                    data.Scores = scores.Result;
                    lock (QueryCacheLock)
                    {
                        QueryCache.Add(key, data);
                    }
                }

                return(data);
            }
            catch
            {
                return(null);
            }
        }
예제 #6
0
        private bool TryGetEntityCommandDefinitionFromQueryCache(
            out EntityCommandDefinition entityCommandDefinition)
        {
            entityCommandDefinition = (EntityCommandDefinition)null;
            if (!this._enableQueryPlanCaching || string.IsNullOrEmpty(this._esqlCommandText))
            {
                return(false);
            }
            EntityClientCacheKey key = new EntityClientCacheKey(this);
            QueryCacheManager    queryCacheManager = this._connection.GetMetadataWorkspace().GetQueryCacheManager();

            if (!queryCacheManager.TryCacheLookup <EntityClientCacheKey, EntityCommandDefinition>(key, out entityCommandDefinition))
            {
                entityCommandDefinition = this.CreateCommandDefinition();
                QueryCacheEntry outQueryCacheEntry = (QueryCacheEntry)null;
                if (queryCacheManager.TryLookupAndAdd(new QueryCacheEntry((QueryCacheKey)key, (object)entityCommandDefinition), out outQueryCacheEntry))
                {
                    entityCommandDefinition = (EntityCommandDefinition)outQueryCacheEntry.GetTarget();
                }
            }
            return(true);
        }
예제 #7
0
        private void PrimeQueryCache <T>(InterfaceType interfaceType, ImplementationType implementationType)
            where T : class, IPersistenceObject
        {
            if (!_table.ContainsKey(interfaceType))
            {
                var objectQuery = _ctx.CreateQuery <BaseServerDataObject_EntityFramework>("[" + GetEntityName(interfaceType) + "]");
#if EAGERLOADING
                objectQuery = AddEagerLoading <T>(objectQuery);
#endif

                // The reason is that "GetEntityName" returns a Query to the baseobject
                // but maybe a derived object is requested. OfType will filter this.
                // This filter has to be added first, so the QueryTranslator can ignore this
                MethodInfo ofType = typeof(ObjectQuery <BaseServerDataObject_EntityFramework>).GetMethod("OfType").MakeGenericMethod(implementationType.Type);
                var        query  = (IQueryable)ofType.Invoke(objectQuery, new object[] { });

                _table[interfaceType] = new QueryCacheEntry(new QueryTranslator <T>(
                                                                new EfQueryTranslatorProvider <T>(
                                                                    metaDataResolver, this.identityStore,
                                                                    query, this, iftFactory, _perfCounter)));
            }
        }
        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);
        }
예제 #9
0
            /// <summary>
            /// Adds query to cache if it is not cached already.
            /// </summary>
            public void TryAdd(IDataContext dataContext, Query <T> query, QueryFlags flags)
            {
                // because Add is less frequent operation than Find, it is fine to have put bigger locks here
                QueryCacheEntry[] cache;
                int version;

                lock (_syncCache)
                {
                    cache   = _cache;
                    version = _version;
                }

                for (var i = 0; i < cache.Length; i++)
                {
                    if (cache[i].Compare(dataContext, query.Expression !, flags))
                    {
                        // already added by another thread
                        return;
                    }
                }

                lock (_syncCache)
                {
                    var priorities   = _indexes;
                    var versionsDiff = _version - version;

                    if (versionsDiff > 0)
                    {
                        cache = _cache;

                        // check only added queries, each version could add 1 query to first position, so we
                        // test only first N queries
                        for (var i = 0; i < cache.Length && i < versionsDiff; i++)
                        {
                            if (cache[i].Compare(dataContext, query.Expression !, flags))
                            {
                                // already added by another thread
                                return;
                            }
                        }
                    }

                    // create new cache instance and reorder items according to priorities to improve Find without
                    // reorder lock
                    var newCache      = new QueryCacheEntry[cache.Length == CacheSize ? CacheSize : cache.Length + 1];
                    var newPriorities = new int[newCache.Length];

                    newCache[0]      = new QueryCacheEntry(query, flags);
                    newPriorities[0] = 0;

                    for (var i = 1; i < newCache.Length; i++)
                    {
                        newCache[i]      = cache[i - 1];
                        newPriorities[i] = i;
                    }

                    _cache   = newCache;
                    _indexes = newPriorities;
                    version  = _version;
                }
            }
예제 #10
0
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption?forMergeOption)
        {
            // Determine the required merge option, with the following precedence:
            // 1. The merge option specified to Execute(MergeOption) as forMergeOption.
            // 2. The merge option set via ObjectQuery.MergeOption.
            // 3. The global default merge option.
            var mergeOption = EnsureMergeOption(forMergeOption, UserSpecifiedMergeOption);

            // If a cached plan is present, then it can be reused if it has the required merge option and streaming behavior
            // (since span and parameters cannot change between executions). However, if the cached
            // plan does not have the required merge option we proceed as if it were not present.
            var plan = _cachedPlan;

            if (plan != null)
            {
                if (plan.MergeOption == mergeOption &&
                    plan.Streaming == EffectiveStreamingBehavior)
                {
                    return(plan);
                }
                else
                {
                    plan = null;
                }
            }

            // There is no cached plan (or it was cleared), so the execution plan must be retrieved from
            // the global query cache (if plan caching is enabled) or rebuilt for the required merge option.
            QueryCacheManager      cacheManager = null;
            EntitySqlQueryCacheKey cacheKey     = null;

            if (PlanCachingEnabled)
            {
                // Create a new cache key that reflects the current state of the Parameters collection
                // and the Span object (if any), and uses the specified merge option.
                cacheKey = new EntitySqlQueryCacheKey(
                    ObjectContext.DefaultContainerName,
                    _queryText,
                    (null == Parameters ? 0 : Parameters.Count),
                    (null == Parameters ? null : Parameters.GetCacheKey()),
                    (null == Span ? null : Span.GetCacheKey()),
                    mergeOption,
                    EffectiveStreamingBehavior,
                    ElementType);

                cacheManager = ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                ObjectQueryExecutionPlan executionPlan = null;
                if (cacheManager.TryCacheLookup(cacheKey, out executionPlan))
                {
                    plan = executionPlan;
                }
            }

            if (plan == null)
            {
                // Either caching is not enabled or the execution plan was not found in the cache
                var queryExpression = Parse();
                Debug.Assert(queryExpression != null, "EntitySqlQueryState.Parse returned null expression?");
                var tree = DbQueryCommandTree.FromValidExpression(
                    ObjectContext.MetadataWorkspace, DataSpace.CSpace, queryExpression,
                    useDatabaseNullSemantics: true);
                plan = _objectQueryExecutionPlanFactory.Prepare(
                    ObjectContext, tree, ElementType, mergeOption, EffectiveStreamingBehavior, Span, null,
                    DbExpressionBuilder.AliasGenerator);

                // If caching is enabled then update the cache now.
                // Note: the logic is the same as in ELinqQueryState.
                if (cacheKey != null)
                {
                    var             newEntry   = new QueryCacheEntry(cacheKey, plan);
                    QueryCacheEntry foundEntry = null;
                    if (cacheManager.TryLookupAndAdd(newEntry, out foundEntry))
                    {
                        // If TryLookupAndAdd returns 'true' then the entry was already present in the cache when the attempt to add was made.
                        // In this case the existing execution plan should be used.
                        plan = (ObjectQueryExecutionPlan)foundEntry.GetTarget();
                    }
                }
            }

            if (Parameters != null)
            {
                Parameters.SetReadOnly(true);
            }

            // Update the cached plan with the newly retrieved/prepared plan
            _cachedPlan = plan;

            // Return the execution plan
            return(plan);
        }
예제 #11
0
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption?forMergeOption)
        {
            Debug.Assert(Span == null, "Include span specified on compiled LINQ-based ObjectQuery instead of within the expression tree?");

            // If this query has already been prepared, its current execution plan may no longer be valid.
            var plan = _cachedPlan;

            if (plan != null)
            {
                // Was a merge option specified in the call to Execute(MergeOption) or set via ObjectQuery.MergeOption?
                var explicitMergeOption = GetMergeOption(forMergeOption, UserSpecifiedMergeOption);

                // If a merge option was explicitly specified, and it does not match the plan's merge option, then the plan is no longer valid.
                // If the context flag UseCSharpNullComparisonBehavior was modified, then the plan is no longer valid.
                if ((explicitMergeOption.HasValue &&
                     explicitMergeOption.Value != plan.MergeOption)
                    ||
                    _recompileRequired()
                    ||
                    ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior != _useCSharpNullComparisonBehavior)
                {
                    plan = null;
                }
            }

            // The plan may have been invalidated above, or this query may never have been prepared.
            if (plan == null)
            {
                // Metadata is required to generate the execution plan.
                ObjectContext.EnsureMetadata();

                // Reset internal state
                _recompileRequired = null;
                ResetParameters();

                // Translate LINQ expression to a DbExpression
                var converter       = CreateExpressionConverter();
                var queryExpression = converter.Convert();

                // This delegate tells us when a part of the expression tree has changed requiring a recompile.
                _recompileRequired = converter.RecompileRequired;

                // Determine the merge option, with the following precedence:
                // 1. A merge option was specified explicitly as the argument to Execute(MergeOption).
                // 2. The user has set the MergeOption property on the ObjectQuery instance.
                // 3. A merge option has been extracted from the 'root' query and propagated to the root of the expression tree.
                // 4. The global default merge option.
                var mergeOption = EnsureMergeOption(
                    forMergeOption,
                    UserSpecifiedMergeOption,
                    converter.PropagatedMergeOption);

                _useCSharpNullComparisonBehavior = ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;

                // If parameters were aggregated from referenced (non-LINQ) ObjectQuery instances then add them to the parameters collection
                _linqParameters = converter.GetParameters();
                if (_linqParameters != null &&
                    _linqParameters.Any())
                {
                    var currentParams = EnsureParameters();
                    currentParams.SetReadOnly(false);
                    foreach (var pair in _linqParameters)
                    {
                        // Note that it is safe to add the parameter directly only
                        // because parameters are cloned before they are added to the
                        // converter's parameter collection, or they came from this
                        // instance's parameter collection in the first place.
                        var convertedParam = pair.Item1;
                        currentParams.Add(convertedParam);
                    }
                    currentParams.SetReadOnly(true);
                }

                // Try retrieving the execution plan from the global query cache (if plan caching is enabled).
                QueryCacheManager cacheManager = null;
                LinqQueryCacheKey cacheKey     = null;
                if (PlanCachingEnabled && !_recompileRequired())
                {
                    // Create a new cache key that reflects the current state of the Parameters collection
                    // and the Span object (if any), and uses the specified merge option.
                    string expressionKey;
                    if (ExpressionKeyGen.TryGenerateKey(queryExpression, out expressionKey))
                    {
                        cacheKey = new LinqQueryCacheKey(
                            expressionKey,
                            (null == Parameters ? 0 : Parameters.Count),
                            (null == Parameters ? null : Parameters.GetCacheKey()),
                            (null == converter.PropagatedSpan ? null : converter.PropagatedSpan.GetCacheKey()),
                            mergeOption,
                            _useCSharpNullComparisonBehavior,
                            ElementType);

                        cacheManager = ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                        ObjectQueryExecutionPlan executionPlan = null;
                        if (cacheManager.TryCacheLookup(cacheKey, out executionPlan))
                        {
                            plan = executionPlan;
                        }
                    }
                }

                // If execution plan wasn't retrieved from the cache, build a new one and cache it.
                if (plan == null)
                {
                    var tree = DbQueryCommandTree.FromValidExpression(ObjectContext.MetadataWorkspace, DataSpace.CSpace, queryExpression);
                    plan = _objectQueryExecutionPlanFactory.Prepare(
                        ObjectContext, tree, ElementType, mergeOption, converter.PropagatedSpan, null, converter.AliasGenerator);

                    // If caching is enabled then update the cache now.
                    // Note: the logic is the same as in EntitySqlQueryState.
                    if (cacheKey != null)
                    {
                        var             newEntry   = new QueryCacheEntry(cacheKey, plan);
                        QueryCacheEntry foundEntry = null;
                        if (cacheManager.TryLookupAndAdd(newEntry, out foundEntry))
                        {
                            // If TryLookupAndAdd returns 'true' then the entry was already present in the cache when the attempt to add was made.
                            // In this case the existing execution plan should be used.
                            plan = (ObjectQueryExecutionPlan)foundEntry.GetTarget();
                        }
                    }
                }

                // Remember the current plan in the local cache, so that we don't have to recalc the key and look into the global cache
                // if the same instance of query gets executed more than once.
                _cachedPlan = plan;
            }

            // Evaluate parameter values for the query.
            if (_linqParameters != null)
            {
                foreach (var pair in _linqParameters)
                {
                    var parameter           = pair.Item1;
                    var parameterExpression = pair.Item2;
                    if (null != parameterExpression)
                    {
                        parameter.Value = parameterExpression.EvaluateParameter(null);
                    }
                }
            }

            return(plan);
        }