public override TResult ExecuteAsync <TResult>(Expression expression, CancellationToken cancellationToken = default) { var cachingResult = ReadFromCache <TResult>(expression); if (cachingResult.HasResult) { return(cachingResult.WrapAsyncResult(cachingResult.CacheEntry.Value)); } var result = base.ExecuteAsync <TResult>(cachingResult.Expression, cancellationToken); if (!cachingResult.CanPut || cancellationToken.IsCancellationRequested) { return(result); } using (var scope = new DbContextScope((HookingDbContext)_currentContext.Context, lazyLoading: false)) { var cacheValue = cachingResult.ConvertQueryAsyncResult(result).Await(); if (cacheValue.Count <= cachingResult.Policy.MaxRows.Value) { var entry = new DbCacheEntry { Key = cachingResult.CacheKey, Value = cacheValue.Value, ValueType = cacheValue.Value?.GetType() }; _cache.Put(cachingResult.CacheKey, entry, cachingResult.Policy); Log(DbCachingEventId.QueryResultCached, "Has put query result to cache. Key: {0}, Type: {1}, Policy: {2}.", cachingResult.CacheKey.Key, typeof(TResult), cachingResult.Policy); } else { Log(DbCachingEventId.MaxRowsExceeded, "Max rows limit exceeded. Will not cache. Actual: {0}, Limit: {1} Key: {2}, Type: {3}.", cacheValue.Count, cachingResult.Policy.MaxRows.Value, cachingResult.CacheKey.Key, typeof(TResult)); } return(cachingResult.WrapAsyncResult(cacheValue.Value)); } }
/// <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="queryExecutor">How to run the query.</param> /// <returns>The value that results from executing the specified query.</returns> private TResult ExecuteInternal <TResult>(Expression expression, Func <Expression, TResult> queryExecutor) { var cachingResult = ReadFromCache <TResult>(expression); if (cachingResult.HasResult) { return(cachingResult.CachedValue); } var queryResult = queryExecutor(cachingResult.Expression); if (!cachingResult.CanPut) { return(queryResult); } using (var scope = new DbContextScope((HookingDbContext)_currentContext.Context, lazyLoading: false)) { var cacheValue = cachingResult.ConvertQueryResult(queryResult); if (cacheValue.Count <= cachingResult.Policy.MaxRows.Value) { var entry = new DbCacheEntry { Key = cachingResult.CacheKey, Value = cacheValue.Value, ValueType = cacheValue.Value?.GetType() }; _cache.Put(cachingResult.CacheKey, entry, cachingResult.Policy); Log(DbCachingEventId.QueryResultCached, "Has put query result to cache. Key: {0}, Type: {1}, Policy: {2}.", cachingResult.CacheKey.Key, typeof(TResult), cachingResult.Policy); } else { Log(DbCachingEventId.MaxRowsExceeded, "Max rows limit exceeded. Will not cache. Actual: {0}, Limit: {1} Key: {2}, Type: {3}.", cacheValue.Count, cachingResult.Policy.MaxRows.Value, cachingResult.CacheKey.Key, typeof(TResult)); } return((TResult)cacheValue.Value); } }
public void Put(DbCacheKey key, DbCacheEntry value, DbCachingPolicy policy) { var cacheKey = BuildKey(key.Key); using (_cache.AcquireKeyLock(cacheKey)) { _cache.Put(cacheKey, value, new CacheEntryOptions().ExpiresIn(policy.ExpirationTimeout.Value)); foreach (var set in key.EntitySets) { var lookup = GetLookupSet(set); lookup.Add(cacheKey); } } }
protected void InvalidateItem(string key, DbCacheEntry entry) { // Remove item itself from cache _cache.Remove(key); // Remove this key in all lookups foreach (var set in entry.Key.EntitySets) { var lookup = GetLookupSet(set, false); if (lookup != null) { lookup.Remove(key); } } }