public void TestCacheInvalidationWithTwoRoots()
        {
            _cacheService.InsertValue("EF_key1", "value1", new HashSet <string> {
                "entity1.model", "entity2.model"
            });

            _cacheService.InsertValue("EF_key2", "value2", new HashSet <string> {
                "entity1.model", "entity2.model"
            });


            var value1 = _cacheService.GetValue("EF_key1");

            Assert.IsNotNull(value1);

            var value2 = _cacheService.GetValue("EF_key2");

            Assert.IsNotNull(value2);

            _cacheService.InvalidateCacheDependencies(new[] { "entity2.model" });

            value1 = _cacheService.GetValue("EF_key1");
            Assert.IsNull(value1);

            value2 = _cacheService.GetValue("EF_key2");
            Assert.IsNull(value2);
        }
コード例 #2
0
        /// <summary>
        /// Reads data from cache or cache it and then returns the result
        /// </summary>
        public T ProcessExecutedCommands <T>(DbCommand command, DbContext context, T result)
        {
            if (result is EFTableRowsDataReader rowsReader)
            {
                _logger.LogDebug(CacheableEventId.CacheHit, $"Returning the cached TableRows[{rowsReader.TableName}].");
                return(result);
            }

            if (_cacheDependenciesProcessor.InvalidateCacheDependencies(command, context, new EFCachePolicy()))
            {
                return(result);
            }

            var allEntityTypes = _sqlCommandsProcessor.GetAllTableNames(context);
            var cachePolicy    = _cachePolicyParser.GetEFCachePolicy(command.CommandText, allEntityTypes);

            if (cachePolicy == null)
            {
                return(result);
            }

            var efCacheKey = _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy);

            if (result is int data)
            {
                _cacheService.InsertValue(efCacheKey, new EFCachedData {
                    NonQuery = data
                }, cachePolicy);
                _logger.LogDebug(CacheableEventId.QueryResultCached, $"[{data}] added to the cache[{efCacheKey}].");
                return(result);
            }

            if (result is DbDataReader dataReader)
            {
                EFTableRows tableRows;
                using (var dbReaderLoader = new EFDataReaderLoader(dataReader))
                {
                    tableRows = dbReaderLoader.LoadAndClose();
                }

                _cacheService.InsertValue(efCacheKey, new EFCachedData {
                    TableRows = tableRows
                }, cachePolicy);
                _logger.LogDebug(CacheableEventId.QueryResultCached, $"TableRows[{tableRows.TableName}] added to the cache[{efCacheKey}].");
                return((T)(object)new EFTableRowsDataReader(tableRows));
            }

            if (result is object)
            {
                _cacheService.InsertValue(efCacheKey, new EFCachedData {
                    Scalar = result
                }, cachePolicy);
                _logger.LogDebug(CacheableEventId.QueryResultCached, $"[{result}] added to the cache[{efCacheKey}].");
                return(result);
            }

            return(result);
        }
        /// <summary>
        /// Reads data from cache or cache it and then returns the result
        /// </summary>
        public T ProcessExecutedCommands <T>(DbCommand command, DbContext context, T result, [CallerMemberName] string methodName = null)
        {
            if (result is EFTableRowsDataReader rowsReader)
            {
                _logger.LogInformation(CacheableEventId.CacheHit, $"Using the TableRows[{rowsReader.TableName}] from the cache.");
                return(result);
            }

            if (_cacheDependenciesProcessor.InvalidateCacheDependencies(command, context, new EFCachePolicy()))
            {
                return(result);
            }

            var cachePolicy = _cachePolicyParser.GetEFCachePolicy(command.CommandText);

            if (cachePolicy != null)
            {
                var efCacheKey = _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy);

                if (result is int data)
                {
                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        NonQuery = data
                    }, cachePolicy);
                    _logger.LogInformation(CacheableEventId.QueryResultCached, $"[{data}] added to the cache[{efCacheKey}].");
                    return(result);
                }

                if (result is DbDataReader dataReader)
                {
                    EFTableRows tableRows;
                    using (var dbReaderLoader = new EFDataReaderLoader(dataReader))
                    {
                        tableRows = dbReaderLoader.LoadAndClose();
                    }

                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        TableRows = tableRows
                    }, cachePolicy);
                    _logger.LogInformation(CacheableEventId.QueryResultCached, $"TableRows[{tableRows.TableName}] added to the cache[{efCacheKey}].");
                    return((T)(object)new EFTableRowsDataReader(tableRows));
                }

                if (result is object)
                {
                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        Scalar = result
                    }, cachePolicy);
                    _logger.LogInformation(CacheableEventId.QueryResultCached, $"[{result}] added to the cache[{efCacheKey}].");
                    return(result);
                }
            }

            return(result);
        }
コード例 #4
0
        /// <summary>
        /// Executes the query represented by a specified expression tree to cache its results.
        /// </summary>
        /// <param name="expression">An expression tree that represents a LINQ query.</param>
        /// <param name="materializer">How to run the query.</param>
        /// <returns>The value that results from executing the specified query.</returns>
        public object Materialize(Expression expression, Func <object> materializer)
        {
            lock (_syncLock)
            {
                var cacheKey = _cacheKeyProvider.GetEFCacheKey(_query, expression, _saltKey);
                _debugInfo.EFCacheKey = cacheKey;
                var queryCacheKey = cacheKey.KeyHash;
                var result        = _cacheServiceProvider.GetValue(queryCacheKey);
                if (Equals(result, _cacheServiceProvider.NullObject))
                {
                    _debugInfo.IsCacheHit = true;
                    return(null);
                }

                if (result != null)
                {
                    _debugInfo.IsCacheHit = true;
                    return(result);
                }

                result = materializer();

                _cacheServiceProvider.InsertValue(queryCacheKey, result, cacheKey.CacheDependencies);

                return(result);
            }
        }
コード例 #5
0
        /// <summary>
        /// Executes the query represented by a specified expression tree to cache its results.
        /// </summary>
        /// <param name="expression">An expression tree that represents a LINQ query.</param>
        /// <param name="materializer">How to run the query.</param>
        /// <returns>The value that results from executing the specified query.</returns>
        public object Materialize(Expression expression, Func <object> materializer)
        {
            var cacheKey = _cacheKeyProvider.GetEFCacheKey(
                _query,
                expression,
                _efCachePolicy.KeyHashPrefix,
                _efCachePolicy.SaltKey);

            _debugInfo.EFCacheKey = cacheKey;
            var queryCacheKey = cacheKey.KeyHash;
            var result        = _cacheServiceProvider.GetValue(queryCacheKey);

            if (result != null)
            {
                _debugInfo.IsCacheHit = true;
                return(result);
            }

            result = materializer();

            _cacheServiceProvider.StoreRootCacheKeys(cacheKey.CacheDependencies);
            if (_efCachePolicy.AbsoluteExpiration == null)
            {
                _efCachePolicy.AbsoluteExpiration = DateTime.Now.AddMinutes(20);
            }
            _cacheServiceProvider.InsertValue(
                queryCacheKey,
                result,
                cacheKey.CacheDependencies,
                _efCachePolicy.AbsoluteExpiration.Value,
                _efCachePolicy.Priority);

            return(result);
        }
コード例 #6
0
        public void TestCacheInvalidationWithTwoRoots()
        {
            _cacheService.StoreRootCacheKeys(new[] { "entity1.model", "entity2.model" });
            _cacheService.InsertValue("EF_key1", "value1", new[] { "entity1.model", "entity2.model" }, DateTime.Now.AddMinutes(10));

            _cacheService.StoreRootCacheKeys(new[] { "entity1.model", "entity2.model" });
            _cacheService.InsertValue("EF_key2", "value2", new[] { "entity1.model", "entity2.model" }, DateTime.Now.AddMinutes(10));


            var value1 = _cacheService.GetValue("EF_key1");

            Assert.IsNotNull(value1);

            var value2 = _cacheService.GetValue("EF_key2");

            Assert.IsNotNull(value2);

            _cacheService.InvalidateCacheDependencies(new[] { "entity2.model" });

            value1 = _cacheService.GetValue("EF_key1");
            Assert.IsNull(value1);

            value2 = _cacheService.GetValue("EF_key2");
            Assert.IsNull(value2);

            var keys = _cacheService.GetAllEFCachedKeys();
            var key1 = keys.FirstOrDefault(key => key == "EF_key1");

            Assert.IsNull(key1);
            Assert.AreEqual(0, keys.Count);
        }
コード例 #7
0
        /// <summary>
        /// Executes the query represented by a specified expression tree to cache its results.
        /// </summary>
        /// <param name="expression">An expression tree that represents a LINQ query.</param>
        /// <param name="materializer">How to run the query.</param>
        /// <returns>The value that results from executing the specified query.</returns>
        public async Task <T> MaterializeAsync <T>(Expression expression, Func <Task <T> > materializer)
        {
            await _semaphoreSlim.WaitAsync();

            try
            {
                var cacheResult = readFromCache <T>(expression);
                if (cacheResult.CanRead)
                {
                    return(cacheResult.Result);
                }

                var result = await materializer();

                _cacheServiceProvider.InsertValue(cacheResult.CacheKey.KeyHash, result,
                                                  cacheResult.CacheKey.CacheDependencies, _cachePolicy);
                return(result);
            }
            finally
            {
                _semaphoreSlim.Release();
            }
        }
        /// <summary>
        /// Reads data from cache or cache it and then returns the result
        /// </summary>
        public T ProcessExecutedCommands <T>(DbCommand command, DbContext context, T result)
        {
            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            if (result is EFTableRowsDataReader rowsReader)
            {
                _logger.LogDebug(CacheableEventId.CacheHit, $"Returning the cached TableRows[{rowsReader.TableName}].");
                return(result);
            }

            var commandText = command.CommandText;
            var cachePolicy = getCachePolicy(context, commandText);
            var efCacheKey  = _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy ?? new EFCachePolicy());

            if (_cacheDependenciesProcessor.InvalidateCacheDependencies(commandText, efCacheKey))
            {
                return(result);
            }

            if (cachePolicy == null)
            {
                _logger.LogDebug($"Skipping a none-cachable command[{commandText}].");
                return(result);
            }

            if (result is int data)
            {
                if (!shouldSkipCachingResults(commandText, data))
                {
                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        NonQuery = data
                    }, cachePolicy);
                    _logger.LogDebug(CacheableEventId.QueryResultCached, $"[{data}] added to the cache[{efCacheKey}].");
                }
                return(result);
            }

            if (result is DbDataReader dataReader)
            {
                EFTableRows tableRows;
                using (var dbReaderLoader = new EFDataReaderLoader(dataReader))
                {
                    tableRows = dbReaderLoader.LoadAndClose();
                }

                if (!shouldSkipCachingResults(commandText, tableRows))
                {
                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        TableRows = tableRows
                    }, cachePolicy);
                    _logger.LogDebug(CacheableEventId.QueryResultCached, $"TableRows[{tableRows.TableName}] added to the cache[{efCacheKey}].");
                }
                return((T)(object)new EFTableRowsDataReader(tableRows));
            }

            if (result is object)
            {
                if (!shouldSkipCachingResults(commandText, result))
                {
                    _cacheService.InsertValue(efCacheKey, new EFCachedData {
                        Scalar = result
                    }, cachePolicy);
                    _logger.LogDebug(CacheableEventId.QueryResultCached, $"[{result}] added to the cache[{efCacheKey}].");
                }
                return(result);
            }

            return(result);
        }