/// <summary> /// 尝试获取指定表达式的缓存。 /// </summary> /// <param name="expression"></param> /// <param name="func">当缓存不存在时,创建缓存数据的函数。</param> /// <returns></returns> internal static Delegate TryGetDelegate(Expression expression, Func <LambdaExpression> func) { var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>(); var option = section == null ? TranslateOptions.Default : section.Options; var result = CacheableChecker.Check(expression); if (!result.Required || (result.Enabled == null && !option.CacheParsing) || result.Enabled == false) { return(func().Compile()); } var cacheKey = ExpressionKeyGenerator.GetKey(expression, "Trans"); cacheKey = NativeCacheKeyContext.GetKey(cacheKey); return(MemoryCacheManager.Instance.TryGet(cacheKey, () => { var lambdaExp = func() as LambdaExpression; var segment = SegmentFinder.Find(expression); if (segment != null) { //将表达式内的 Segment 替换成参数 var segParExp = Expression.Parameter(typeof(IDataSegment), "g"); var newExp = SegmentReplacer.Repalce(lambdaExp.Body, segParExp); var parameters = new List <ParameterExpression>(lambdaExp.Parameters); parameters.Insert(1, segParExp); lambdaExp = Expression.Lambda(newExp, parameters.ToArray()); } return lambdaExp.Compile(); }, () => new RelativeTime(result.Expired ?? TimeSpan.FromSeconds(option.CacheParsingTimes)))); }
/// <summary> /// 尝试通过表达式获取执行后的结果缓存。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression"></param> /// <param name="func"></param> /// <returns></returns> internal static T TryGet <T>(Expression expression, Func <T> func) { var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>(); var option = section == null ? TranslateOptions.Default : section.Options; var result = CacheableChecker.Check(expression); //没有开启数据缓存 if ((result.Enabled == null && !option.CacheExecution) || result.Enabled == false) { return(func()); } var cacheMgr = CacheManagerFactory.CreateManager(); if (cacheMgr == null) { return(func()); } var cacheKey = ExpressionKeyGenerator.GetKey(expression, "Exec"); cacheKey = NativeCacheKeyContext.GetKey(cacheKey); Reference(cacheKey, expression); var segment = SegmentFinder.Find(expression); var pager = segment as DataPager; var cacheFunc = new Func <CacheItem <T> >(() => { var data = EnumerateData(func()); var isEnumerable = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(IEnumerable <>); if (isEnumerable) { var elementType = typeof(T).GetEnumerableElementType(); var method = typeof(Enumerable).GetMethod(nameof(Enumerable.ToList)).MakeGenericMethod(elementType); data = (T)method.Invoke(null, new object[] { data }); } var total = 0; if (pager != null) { total = pager.RecordCount; } return(new CacheItem <T> { Data = data, Total = total }); }); var cacheItem = cacheMgr.TryGet(cacheKey, cacheFunc, () => new RelativeTime(result.Expired ?? TimeSpan.FromSeconds(option.CacheExecutionTimes))); if (pager != null) { pager.RecordCount = cacheItem.Total; } return(cacheItem.Data); }
/// <summary> /// 判断是否被缓存。 /// </summary> /// <param name="expression"></param> /// <returns></returns> internal static bool CanCache(Expression expression) { var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>(); var option = section == null ? TranslateOptions.Default : section.Options; var result = CacheableChecker.Check(expression); return(typeof(IQueryable).IsAssignableFrom(expression.Type) && (result.Enabled == true || (result.Enabled == null && option.CacheExecution))); }
/// <summary> /// 异步的,尝试通过表达式获取执行后的结果缓存。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression"></param> /// <param name="context"></param> /// <param name="creator"></param> /// <param name="cancellationToken"></param> /// <returns></returns> async Task <T> IExecuteCache.TryGetAsync <T>(Expression expression, ExecuteCacheContext context, Func <CancellationToken, Task <T> > creator, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>(); var option = section == null ? TranslateOptions.Default : section.Options; if (context.Enabled == true || (context.Enabled == null && option.CacheExecution)) { TryExpire(expression); } var evaluator = _serviceProvider.TryGetService <IExecuteCacheEvaluator>(); var result = CacheableChecker.Check(evaluator, expression); //没有开启数据缓存 if ((result.Enabled == null && (context.Enabled == false || (context.Enabled == null && !option.CacheExecution))) || result.Enabled == false || _cacheMgr == null) { return(await creator(cancellationToken)); } var generator = _serviceProvider.TryGetService <IExecuteCacheKeyGenerator>(() => ExpressionKeyGenerator.Instance); var cacheKey = _serviceProvider.GetCacheKey(generator.Generate(expression, CACHE_KEY)); Tracer.Debug($"DefaultExecuteCache access to '{cacheKey}'"); var segment = SegmentFinder.Find(expression); var pager = segment as DataPager; using var edps = new EntityDeserializeProcessorScope(); var cacheItem = _cacheMgr.TryGet(cacheKey, () => HandleCacheItem(cacheKey, expression, creator(cancellationToken).AsSync(), pager), () => new RelativeTime(GetExpire(result, option, context))); if (pager != null) { pager.RecordCount = cacheItem.Total; } TryStartRunner(); return(cacheItem.Data); }
/// <summary> /// 尝试获取指定表达式的缓存。 /// </summary> /// <param name="expression"></param> /// <param name="context"></param> /// <param name="creator">当缓存不存在时,创建缓存数据的函数。</param> /// <returns></returns> Delegate IQueryCache.TryGetDelegate(Expression expression, QueryCacheContext context, Func <LambdaExpression> creator) { var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>(); var option = section == null ? TranslateOptions.Default : section.Options; var result = CacheableChecker.Check(expression); if (!result.Required || (result.Enabled == null && (context.Enabled == false || (context.Enabled == null && !option.CacheParsing))) || result.Enabled == false) { return(creator().Compile()); } var generator = _serviceProvider.TryGetService <IQueryCacheKeyGenerator>(() => ExpressionKeyGenerator.Instance); var cacheKey = _serviceProvider.GetCacheKey(generator.Generate(expression, "Trans")); Tracer.Debug($"QueryCache access to '{cacheKey}'"); var cacheMgr = _serviceProvider.TryGetService <IMemoryCacheManager>(() => MemoryCacheManager.Instance); return(cacheMgr.TryGet(cacheKey, () => { var lambdaExp = creator() as LambdaExpression; var segment = SegmentFinder.Find(expression); if (segment != null) { //将表达式内的 Segment 替换成参数 var segParExp = Expression.Parameter(typeof(IDataSegment), "g"); var newExp = SegmentReplacer.Repalce(lambdaExp.Body, segParExp); var parameters = new List <ParameterExpression>(lambdaExp.Parameters); parameters.Insert(1, segParExp); lambdaExp = Expression.Lambda(newExp, parameters.ToArray()); } return lambdaExp.Compile(); }, () => new RelativeTime(GetExpire(result, option, context)))); }