예제 #1
0
        /// <summary>
        /// Refer to CachingQuerySqlBuilder.MutateResultToMatchCurrentQuery
        /// </summary>
        internal static QueryResult MutateResultToMatchCurrentQuery(CachingQueryRunnerValue cacheValue, StructuredQuery currentQuery)
        {
            if (cacheValue == null)
            {
                throw new ArgumentNullException("cacheValue");
            }
            if (currentQuery == null)
            {
                throw new ArgumentNullException("currentQuery");
            }

            // Clone result
            QueryBuild  queryBuild = CachingQuerySqlBuilder.MutateResultToMatchCurrentQuery(cacheValue.QueryResult.QueryBuild, cacheValue.OriginalQuery, currentQuery);
            QueryResult result     = cacheValue.QueryResult.ShallowClone(queryBuild);

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Try to get the value from cache, with logging.
        /// </summary>
        private bool TryGetOrAdd(CachingQueryRunnerKey key, MessageContext msg, out CachingQueryRunnerValue result, Func <CachingQueryRunnerKey, CachingQueryRunnerValue> valueFactory)
        {
            bool foundValue;

            foundValue = Cache.TryGetOrAdd(key, out result, valueFactory);

            msg.Append(() => "CachingQueryRunner key:" + key);
            if (foundValue)
            {
                var cacheValue = result;
                msg.Append(() => "CachingQueryRunner cache hit");
                msg.Append(() => $"Entry originally cached at {cacheValue.CacheTime}");
            }
            else
            {
                msg.Append(() => "CachingQueryRunner cache miss");
            }

            return(foundValue);
        }
예제 #3
0
        /// <summary>
        /// Build the SQL, or collect it from cache.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public QueryResult ExecuteQuery(StructuredQuery query, QuerySettings settings)
        {
            // Validate
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }
            if (QueryRunner == null)
            {
                throw new InvalidOperationException("QueryRunner not set.");
            }
            if (settings == null)
            {
                settings = new QuerySettings( );
            }

            // Determine if we should cache .. and the cache key
            QueryBuild            builtQuery;
            CachingQueryRunnerKey key;
            CacheContext          queryBuilderCacheContext;

            using (queryBuilderCacheContext = new CacheContext())
            {
                key = CreateCacheKeyAndQuery(query, settings, out builtQuery);
            }

            // A null key means that the ersult should not participate in caching
            if (key == null)
            {
                return(RunQueryImpl(query, settings, builtQuery));
            }

            CachingQueryRunnerValue cacheValue;

            using (MessageContext msg = new MessageContext("Reports"))
            {
                // Check for force recalculation
                if (settings.RefreshCachedResult)
                {
                    msg.Append(() => "CachingQueryRunner refreshed forced");
                    Cache.Remove(key);
                }

                // Run query
                bool fromCache = TryGetOrAdd(key, msg, out cacheValue, callbackKey =>
                {
                    using (CacheContext cacheContext = new CacheContext( ))
                    {
                        QueryResult queryResult = RunQueryImpl(query, settings, builtQuery);
                        cacheValue = new CachingQueryRunnerValue(query, queryResult);

                        // Add the cache context entries to the appropriate CacheInvalidator
                        _cacheInvalidator.AddInvalidations(cacheContext, callbackKey);
                        _cacheInvalidator.AddInvalidations(queryBuilderCacheContext, callbackKey);
                    }

                    return(cacheValue);
                });

                if (fromCache && CacheContext.IsSet())
                {
                    using (CacheContext cacheContext = CacheContext.GetContext( ))
                    {
                        // Add the already stored changes that should invalidate this cache
                        // entry to any outer or containing cache contexts.
                        cacheContext.AddInvalidationsFor(_cacheInvalidator, key);
                    }
                }
            }

            if (cacheValue == null)
            {
                throw new Exception("Assert false");
            }

            // Mutate returned result to be suitable for current query
            QueryResult result;

            if (cacheValue.OriginalQuery == query)
            {
                result = cacheValue.QueryResult;
            }
            else
            {
                result = MutateResultToMatchCurrentQuery(cacheValue, query);
            }

            return(result);
        }