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); }
/// <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); }
/// <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); } }
/// <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); }
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); }
/// <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); }