コード例 #1
0
        /// <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))));
        }
コード例 #2
0
ファイル: Extensions.cs プロジェクト: wushian/fireasy2
        /// <summary>
        /// 将查询转换为带分页信息的结构输出。查询中需要使用 Segment 扩展方法带入 <see cref="IPager"/> 分页对象。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static PaginalResult <T> ToPaginalResult <T>(this IQueryable <T> source)
        {
            var segment = SegmentFinder.Find(source.Expression);
            var list    = source.ToList();

            return(new PaginalResult <T>(list, segment as IPager));
        }
コード例 #3
0
            /// <summary>
            /// 查找表达式中的 <see cref="IDataSegment"/> 对象。
            /// </summary>
            /// <param name="expression"></param>
            /// <returns></returns>
            public static IDataSegment Find(Expression expression)
            {
                var replaer = new SegmentFinder();

                replaer.Visit(expression);
                return(replaer.dataSegment);
            }
コード例 #4
0
        /// <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);
        }
コード例 #5
0
        /// <summary>
        /// 执行 <see cref="Expression"/> 的查询,返回查询结果。
        /// </summary>
        /// <param name="expression">表示 LINQ 查询的表达式树。</param>
        /// <returns>单值对象。</returns>
        /// <exception cref="TranslateException">对 LINQ 表达式解析失败时抛出此异常。</exception>
        public object Execute(Expression expression)
        {
            var efn = TranslateCache.TryGetDelegate(expression, () => (LambdaExpression)GetExecutionPlan(expression));

            if (efn.Method.GetParameters().Length == 2)
            {
                return(efn.DynamicInvoke(service.Database));
            }

            var segment = SegmentFinder.Find(expression);

            return(efn.DynamicInvoke(service.Database, segment));
        }
コード例 #6
0
        /// <summary>
        /// 执行 <see cref="Expression"/> 的查询,返回查询结果。
        /// </summary>
        /// <param name="expression">表示 LINQ 查询的表达式树。</param>
        /// <returns>单值对象。</returns>
        /// <exception cref="TranslateException">对 LINQ 表达式解析失败时抛出此异常。</exception>
        public object Execute(Expression expression)
        {
            var efn = TranslateCache.TryGetDelegate(expression, () => (LambdaExpression)GetExecutionPlan(expression));

            var attrs = GetMethodAttributes(efn.Method);

            if (!attrs.Item2)
            {
                return(efn.DynamicInvoke(service.Database));
            }

            var segment = SegmentFinder.Find(expression);

            return(efn.DynamicInvoke(service.Database, segment));
        }
コード例 #7
0
        /// <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;

            //没有开启数据缓存
            if (!option.DataCacheEnabled)
            {
                return(func());
            }

            var cacheMgr = CacheManagerFactory.CreateManager();

            if (cacheMgr == null)
            {
                return(func());
            }

            var cacheKey = ExpressionKeyGenerator.GetKey(expression, "Exec");

            Reference(cacheKey, expression);

            var segment = SegmentFinder.Find(expression);
            var pager   = segment as DataPager;

            var cacheFunc = new Func <CacheItem <T> >(() =>
            {
                var data  = func();
                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(TimeSpan.FromSeconds(option.DataCacheExpired)));

            if (pager != null)
            {
                pager.RecordCount = cacheItem.Total;
            }

            return(cacheItem.Data);
        }
コード例 #8
0
        /// <summary>
        /// 执行 <see cref="Expression"/> 的查询,返回查询结果。
        /// </summary>
        /// <param name="expression">表示 LINQ 查询的表达式树。</param>
        /// <returns>单值对象。</returns>
        /// <exception cref="TranslateException">对 LINQ 表达式解析失败时抛出此异常。</exception>
        public async Task <TResult> ExecuteAsync <TResult>(Expression expression, CancellationToken cancellationToken = default)
        {
            var efn = TranslateCache.TryGetDelegate(expression, () => (LambdaExpression)GetExecutionPlan(expression));

            var attrs = GetMethodAttributes(efn.Method);

            object result;

            if (attrs.Item1)
            {
                if (attrs.Item2)
                {
                    var segment = SegmentFinder.Find(expression);
                    result = efn.DynamicInvoke(service.Database, segment, cancellationToken);
                }
                else
                {
                    result = efn.DynamicInvoke(service.Database, cancellationToken);
                }
            }
            else
            {
                if (attrs.Item2)
                {
                    var segment = SegmentFinder.Find(expression);
                    result = efn.DynamicInvoke(service.Database, segment);
                }
                else
                {
                    result = efn.DynamicInvoke(service.Database);
                }
            }

            if (result is TResult)
            {
                return((TResult)result);
            }
            else if (result is Task <TResult> task)
            {
                return(task.Result);
            }

            return(default);
コード例 #9
0
ファイル: TranslateCache.cs プロジェクト: luckyJM/fireasy2
        /// <summary>
        /// 尝试获取指定表达式的缓存。
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="func">当缓存不存在时,创建缓存数据的函数。</param>
        /// <returns></returns>
        internal static Expression <Func <IDatabase, object> > TryGet(Expression expression, Func <Expression <Func <IDatabase, object> > > func)
        {
            if (!CachaebleChecker.Check(expression))
            {
                return(func());
            }

            var section = ConfigurationUnity.GetSection <TranslatorConfigurationSection>();
            var option  = section == null ? TranslateOptions.Default : section.Options;

            if (!option.ParseCacheEnabled)
            {
                return(func());
            }

            ClearExpiredKeys();

            var lazy = new Lazy <CacheItem>(() => new CacheItem
            {
                Expression = func(),
                Expired    = DateTime.Now.AddSeconds(option.ParseCacheExpired)
            });

            var cacheKey = GetKey(expression);
            var result   = cache.GetOrAdd(cacheKey, k => lazy.Value);

            //在现有的表达式中查找 IDataSegment,去替换缓存中的 IDataSegment
            //原因是前端需要获得分页信息,如果不进行替换,将无法返回信息
            var segment = SegmentFinder.Find(expression);

            if (segment != null)
            {
                result.Expression = (Expression <Func <IDatabase, object> >)SegmentReplacer.Repalce(result.Expression, segment);
            }

            return(result.Expression);
        }