using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure { public static class MemoryCacheExtentions { private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); /// <summary> /// Создать кеш на основе асинхронного запроса к БД. /// Ключ кеша - полное имя типа T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="memoryCache"></param> /// <param name="query"></param> /// <param name="token"></param> /// <returns></returns> public static Task<IEnumerable<T>> GetOrCreateBasicAsync<T>(this IMemoryCache memoryCache, IQueryable<T> query, CancellationToken token) where T : class { var getter = async (CancellationToken token) => { var entities = await query .AsNoTracking() .ToArrayAsync(token); return entities.AsEnumerable(); }; return memoryCache.GetOrCreateBasicAsync(getter, token); } /// <summary> /// Создать кеш на основе результата выполнения произвольной асинхронной функции. /// Ключ кеша - полное имя типа T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="memoryCache"></param> /// <param name="getterAsync"></param> /// <param name="token"></param> /// <returns></returns> public static Task<IEnumerable<T>> GetOrCreateBasicAsync<T>(this IMemoryCache memoryCache, Func<CancellationToken, Task<IEnumerable<T>>> getterAsync, CancellationToken token) { var key = typeof(T).FullName!; var cache = memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; cacheEntry.SlidingExpiration = CacheOlescence; var entities = await getterAsync(token); return entities; }); return cache!; } /// <summary> /// Создать кеш на основе запроса к БД. /// Ключ кеша - полное имя типа T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="memoryCache"></param> /// <param name="query"></param> /// <returns></returns> public static IEnumerable<T> GetOrCreateBasic<T>(this IMemoryCache memoryCache, IQueryable<T> query) where T : class { var getter = () => query .AsNoTracking() .ToArray(); return memoryCache.GetOrCreateBasic(getter); } /// <summary> /// Создать кеш на основе результата выполнения произвольной функции. /// Ключ кеша - полное имя типа T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="memoryCache"></param> /// <param name="getter"></param> /// <returns></returns> public static IEnumerable<T> GetOrCreateBasic<T>(this IMemoryCache memoryCache, Func<IEnumerable<T>> getter) { var key = typeof(T).FullName!; var cache = memoryCache.GetOrCreate(key, cacheEntry => { cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; cacheEntry.SlidingExpiration = CacheOlescence; return getter(); }); return cache!; } /// <summary> /// Сбросить кеш. /// Ключ кеша - полное имя типа T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="memoryCache"></param> public static void DropBasic<T>(this IMemoryCache memoryCache) where T : class { var key = typeof(T).FullName!; memoryCache.Remove(key); } } }