Ejemplo n.º 1
0
        public override IAsyncEnumerable <Object> Execute(Object dataContext, OeQueryContext queryContext)
        {
            IAsyncEnumerable <Object> asyncEnumerable;
            MethodCallExpression?     countExpression = null;

            if (base.QueryCache.AllowCache)
            {
                asyncEnumerable = GetFromCache <Object>(queryContext, (T)dataContext, out countExpression);
            }
            else
            {
                Expression expression = queryContext.CreateExpression(new OeConstantToVariableVisitor());
                expression = OeEnumerableToQuerableVisitor.Translate(expression);
                expression = TranslateExpression(queryContext.EdmModel, expression);
                IQueryable entitySet = queryContext.EntitySetAdapter.GetEntitySet(dataContext);
                IQueryable query     = entitySet.Provider.CreateQuery(queryContext.TranslateSource(dataContext, expression));
                asyncEnumerable = ((IQueryable <Object>)query).AsAsyncEnumerable();

                if (queryContext.IsQueryCount())
                {
                    expression      = queryContext.CreateCountExpression(query.Expression);
                    countExpression = (MethodCallExpression)OeEnumerableToQuerableVisitor.Translate(expression);
                    countExpression = (MethodCallExpression)TranslateExpression(queryContext.EdmModel, countExpression);
                }
            }

            if (countExpression != null)
            {
                IQueryable query = queryContext.EntitySetAdapter.GetEntitySet(dataContext);
                queryContext.TotalCountOfItems = query.Provider.Execute <int>(countExpression);
            }

            return(asyncEnumerable);
        }
    protected override Expression VisitMethodCall(MethodCallExpression methodCall)
    {
        MethodCallExpression?candidate = MakeCandidateMatch(methodCall);

        CheckEqual(methodCall.Method, candidate?.Method);
        return(base.VisitMethodCall(methodCall));
    }
        public override IAsyncEnumerable <Object> Execute(Object dataContext, OeQueryContext queryContext)
        {
            IEnumerable          enumerable;
            MethodCallExpression?countExpression = null;

            if (base.QueryCache.AllowCache)
            {
                enumerable = GetFromCache <Object>(queryContext, dataContext, out countExpression);
            }
            else
            {
                var        constantToVariableVisitor = new InMemoryConstantToVariableVisitor();
                Expression expression = queryContext.CreateExpression(out IReadOnlyDictionary <ConstantExpression, ConstantNode> constants);
                expression = new OeSingleNavigationVisitor(queryContext.EdmModel).Visit(expression);
                expression = new OeCollectionNavigationVisitor(queryContext.EdmModel).Visit(expression);
                expression = new NullPropagationVisitor().Visit(expression);
                expression = queryContext.TranslateSource(dataContext, expression);
                var func = (Func <IEnumerable>)Expression.Lambda(expression).Compile();
                enumerable = func();

                if (queryContext.IsQueryCount())
                {
                    countExpression = queryContext.CreateCountExpression(expression);
                }
            }

            if (countExpression != null)
            {
                var func = (Func <int>)Expression.Lambda(countExpression).Compile();
                queryContext.TotalCountOfItems = func();
            }

            return(Infrastructure.AsyncEnumeratorHelper.ToAsyncEnumerable(enumerable));
        }
        /// <summary>Determines whether the specified <see cref="MethodCallExpression"/>s are equal.</summary>
        /// <param name="x">The first <see cref="MethodCallExpression"/> to compare.</param>
        /// <param name="y">The second <see cref="MethodCallExpression"/> to compare.</param>
        /// <returns>true if the specified <see cref="MethodCallExpression"/>s are equal; otherwise, false.</returns>
        bool IEqualityComparer <MethodCallExpression> .Equals([AllowNull] MethodCallExpression?x, [AllowNull] MethodCallExpression?y)
        {
            if (ReferenceEquals(x, y))
            {
                return(true);
            }

            if (x == null || y == null)
            {
                return(false);
            }

            return(EqualsMethodCall(x, y, BeginScope()));
        }
            protected override Expression VisitMethodCall(MethodCallExpression node)
            {
                if (node.Arguments.Count > 0 && node.Arguments[0] is MemberExpression navigationProperty)
                {
                    MethodCallExpression?join = GetJoin(navigationProperty);
                    if (join != null)
                    {
                        Expression[] arguments = node.Arguments.ToArray();
                        arguments[0] = join;
                        return(node.Update(node.Object !, arguments));
                    }
                }

                return(base.VisitMethodCall(node));
            }
    protected override string VisitMethodCall(MethodCallExpression?m)
    {
        if (m is null)
        {
            return(string.Empty);
        }

        Type?declaring = m.Method.DeclaringType;

        if (declaring != typeof(SqlTemplate))
        {
            return(base.VisitMethodCall(m));
        }

        if (m.Method.Name != "Arg" && m.Method.Name != "ArgIn")
        {
            throw new NotSupportedException($"Method SqlTemplate.{m.Method.Name} is not supported.");
        }

        ParameterInfo[] parameters = m.Method.GetParameters();
        if (parameters.Length != 1 || parameters[0].ParameterType != typeof(string))
        {
            throw new NotSupportedException(
                      $"Method SqlTemplate.{m.Method.Name}({string.Join(", ", parameters.Select(x => x.ParameterType))} is not supported.");
        }

        Expression arg = m.Arguments[0];
        string?    name;

        if (arg.NodeType == ExpressionType.Constant)
        {
            name = arg.ToString();
        }
        else
        {
            // though... we probably should avoid doing this
            UnaryExpression member = Expression.Convert(arg, typeof(object));
            var             lambda = Expression.Lambda <Func <object> >(member);
            Func <object>   getter = lambda.Compile();
            name = getter().ToString();
        }

        SqlParameters.Add(new SqlTemplate.TemplateArg(RemoveQuote(name)));

        return(Visited
            ? string.Empty
            : $"@{SqlParameters.Count - 1}");
    }
        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression != null && !node.Type.IsEnum && ModelBuilder.PrimitiveTypeHelper.GetPrimitiveType(node.Type) == null)
            {
                IEdmModel?edmModel = _edmModel.GetEdmModel(node.Type);
                if (edmModel != null)
                {
                    MethodCallExpression?join = GetJoin(node.Expression, node);
                    if (join != null)
                    {
                        return(base.VisitMethodCall(join));
                    }
                }
            }

            return(base.VisitMember(node));
        }
Ejemplo n.º 8
0
        public static IQueryable <T> PaginationBy <T>(this IQueryable <T> queryable, Pagination pagination)
        {
            if (pagination == null)
            {
                return(queryable);
            }
            bool isAsc = pagination.sord?.ToLower() == "asc";

            string[]             order     = pagination.sidx?.Split(',') ?? Array.Empty <string>();
            MethodCallExpression?resultExp = null;

            foreach (string item in order)
            {
                string orderPart = item;
                orderPart = Regex.Replace(orderPart, @"\s+", " ");
                string[] orderArray = orderPart.Split(' ');
                string   orderField = orderArray[0];
                if (orderArray.Length == 2)
                {
                    isAsc = orderArray[1].ToLower() == "asc";
                }

                var parameter = Expression.Parameter(typeof(T), "t");
                var property  = typeof(T).GetProperty(orderField);
                if (property == null)
                {
                    continue;
                }
                var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                var orderByExp     = Expression.Lambda(propertyAccess, parameter);
                resultExp = Expression.Call(typeof(Queryable), isAsc ? "OrderBy" : "OrderByDescending",
                                            new Type[] { typeof(T), property.PropertyType }, queryable.Expression,
                                            Expression.Quote(orderByExp));
            }

            if (resultExp != null)
            {
                queryable = queryable.Provider.CreateQuery <T>(resultExp);
            }

            pagination.records = queryable.Count();
            return(queryable.Skip(pagination.rows * (pagination.page - 1)).Take(pagination.rows));
        }
Ejemplo n.º 9
0
    private HandlerMethodExecuteAction?Build()
    {
        MethodInfo?methodInfo = _handlerTargetType.GetMethod("Execute");

        if (methodInfo == null)
        {
            throw new ArgumentException($"Cannot find 'Execute' method in type: '{_handlerTargetType.FullName}'.");
        }

        ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target");
        ParameterExpression methodParameter = Expression.Parameter(typeof(object), "parameter");

        UnaryExpression?instance  = Expression.Convert(targetParameter, _handlerTargetType);
        UnaryExpression?parameter = Expression.Convert(methodParameter, _handlerParameterType);

        MethodCallExpression?methodCall = Expression.Call(instance, methodInfo, parameter);

        return(Expression.Lambda <HandlerMethodExecuteAction>(methodCall, targetParameter, methodParameter).Compile());
    }
Ejemplo n.º 10
0
            protected override Expression VisitMethodCall(MethodCallExpression node)
            {
                var result = base.VisitMethodCall(node);

                if (CauseOfArgumentNull != null)
                {
                    return(result);
                }

                // Only interested in static methods
                if (node.Object != null)
                {
                    return(result);
                }

                if (ThrowsArgumentNullException(node))
                {
                    CauseOfArgumentNull = node;
                }

                return(result);
            }
            protected override Expression VisitMember(MemberExpression node)
            {
                MethodCallExpression?join = GetJoin(node);

                return(join ?? base.VisitMember(node));
            }
Ejemplo n.º 12
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr             = methodCall.Arguments[0];
            var wrapSequence             = false;
            LambdaExpression?groupingKey = null;
            var groupingKind             = GroupingType.Default;

            if (sequenceExpr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.IsQueryable("Select"))
                {
                    var selectParam = (LambdaExpression)call.Arguments[1].Unwrap();
                    var type        = selectParam.Body.Type;

                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        wrapSequence = true;

                        var selectParamBody = selectParam.Body.Unwrap();
                        MethodCallExpression?groupingMethod = null;
                        if (selectParamBody is MemberInitExpression mi)
                        {
                            var assignment = mi.Bindings.OfType <MemberAssignment>().FirstOrDefault(m => m.Member.Name == "Key");
                            if (assignment?.Expression.NodeType == ExpressionType.Call)
                            {
                                var mc = (MethodCallExpression)assignment.Expression;
                                if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup, Methods.LinqToDB.GroupBy.Cube, Methods.LinqToDB.GroupBy.GroupingSets))
                                {
                                    groupingMethod = mc;
                                    groupingKey    = (LambdaExpression)mc.Arguments[0].Unwrap();
                                    if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup))
                                    {
                                        groupingKind = GroupingType.Rollup;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Cube))
                                    {
                                        groupingKind = GroupingType.Cube;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.GroupingSets))
                                    {
                                        groupingKind = GroupingType.GroupBySets;
                                    }
                                    else
                                    {
                                        throw new InvalidOperationException();
                                    }
                                }
                            }
                        }

                        if (groupingMethod != null && groupingKey != null)
                        {
                            sequenceExpr = sequenceExpr.Replace(groupingMethod, groupingKey.Body.Unwrap());
                        }
                    }
                }
            }

            var sequence    = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var keySequence = sequence;

            var groupingType    = methodCall.Type.GetGenericArguments()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap() !;
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap() !;

            if (wrapSequence)
            {
                sequence = new SubQueryContext(sequence);
            }

            sequence = new SubQueryContext(sequence);
            var key = new KeyContext(buildInfo.Parent, keySelector, sequence);

            if (groupingKind != GroupingType.GroupBySets)
            {
                var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key, null);

                var allowed = groupSql.Where(s => !QueryHelper.IsConstant(s.Sql));

                foreach (var sql in allowed)
                {
                    sequence.SelectQuery.GroupBy.Expr(sql.Sql);
                }
            }
            else
            {
                var goupingSetBody = groupingKey !.Body;
                var groupingSets   = EnumGroupingSets(goupingSetBody).ToArray();
                if (groupingSets.Length == 0)
                {
                    throw new LinqException($"Invalid groping sets expression '{goupingSetBody}'.");
                }

                foreach (var groupingSet in groupingSets)
                {
                    var groupSql = builder.ConvertExpressions(keySequence, groupingSet, ConvertFlags.Key, null);
                    sequence.SelectQuery.GroupBy.Items.Add(
                        new SqlGroupingSet(groupSql.Select(s => keySequence.SelectQuery.Select.AddColumn(s.Sql))));
                }
            }

            sequence.SelectQuery.GroupBy.GroupingType = groupingKind;

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element, builder.IsGroupingGuardDisabled);

            Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery);

            return(groupBy);
        }
Ejemplo n.º 13
0
        private IAsyncEnumerable <TResult> GetFromCache <TResult>(OeQueryContext queryContext, DbContext dbContext, out MethodCallExpression?countExpression)
        {
            Cache.OeCacheContext   cacheContext   = queryContext.CreateCacheContext();
            Cache.OeQueryCacheItem?queryCacheItem = base.QueryCache.GetQuery(cacheContext);

            Func <QueryContext, IAsyncEnumerable <TResult> >   queryExecutor;
            IReadOnlyList <Cache.OeQueryCacheDbParameterValue> parameterValues;

            if (queryCacheItem == null)
            {
                var        parameterVisitor = new OeConstantToParameterVisitor();
                Expression expression       = queryContext.CreateExpression(parameterVisitor);
                expression = TranslateExpression(queryContext.EdmModel, expression);
                expression = queryContext.TranslateSource(dbContext, expression);
                expression = OeEnumerableToQuerableVisitor.Translate(expression);

                queryExecutor = dbContext.CreateAsyncQueryExecutor <TResult>(expression);
                if (queryContext.EntryFactory == null)
                {
                    countExpression = null;
                }
                else
                {
                    countExpression = queryContext.CreateCountExpression(expression);
                    countExpression = (MethodCallExpression)OeEnumerableToQuerableVisitor.Translate(countExpression);
                    countExpression = (MethodCallExpression)TranslateExpression(queryContext.EdmModel, countExpression);
                }

                cacheContext = queryContext.CreateCacheContext(parameterVisitor.ConstantToParameterMapper);
                base.QueryCache.AddQuery(cacheContext, queryExecutor, countExpression, queryContext.EntryFactory);
                parameterValues = parameterVisitor.ParameterValues;
            }
            else
            {
                queryExecutor             = (Func <QueryContext, IAsyncEnumerable <TResult> >)queryCacheItem.Query;
                queryContext.EntryFactory = queryCacheItem.EntryFactory;
                countExpression           = queryCacheItem.CountExpression;
                parameterValues           = cacheContext.ParameterValues;
            }

            var          queryContextFactory = dbContext.GetService <IQueryContextFactory>();
            QueryContext efQueryContext      = queryContextFactory.Create();

            foreach (Cache.OeQueryCacheDbParameterValue parameterValue in parameterValues)
            {
                efQueryContext.AddParameter(parameterValue.ParameterName, parameterValue.ParameterValue);
            }

            if (queryContext.IsQueryCount() && countExpression != null)
            {
                countExpression = (MethodCallExpression)queryContext.TranslateSource(dbContext, countExpression);
                countExpression = (MethodCallExpression) new OeParameterToVariableVisitor().Translate(countExpression, parameterValues);
            }
            else
            {
                countExpression = null;
            }

            return(queryExecutor(efQueryContext));
        }
Ejemplo n.º 14
0
        private IEnumerable GetFromCache <TResult>(OeQueryContext queryContext, Object dataContext, out MethodCallExpression?countExpression)
        {
            Cache.OeCacheContext   cacheContext   = queryContext.CreateCacheContext();
            Cache.OeQueryCacheItem?queryCacheItem = base.QueryCache.GetQuery(cacheContext);

            InMemoryExecutor executor;
            IReadOnlyList <Cache.OeQueryCacheDbParameterValue> parameterValues;

            if (queryCacheItem == null)
            {
                var        variableVisitor = new InMemoryConstantToVariableVisitor();
                Expression expression      = queryContext.CreateExpression(out IReadOnlyDictionary <ConstantExpression, ConstantNode> constants);
                expression = variableVisitor.Translate(expression, constants);
                expression = new OeSingleNavigationVisitor(queryContext.EdmModel).Visit(expression);
                expression = new OeCollectionNavigationVisitor(queryContext.EdmModel).Visit(expression);
                expression = new NullPropagationVisitor().Visit(expression);
                expression = new InMemorySourceVisitor(queryContext.EdmModel, variableVisitor.Parameters).Visit(expression);
                var query = (Func <IEnumerable>)Expression.Lambda(expression).Compile();

                if (queryContext.EntryFactory == null)
                {
                    countExpression = null;
                }
                else
                {
                    countExpression = queryContext.CreateCountExpression(expression);
                }

                cacheContext = queryContext.CreateCacheContext(variableVisitor.ConstantToParameterMapper);
                executor     = new InMemoryExecutor(query, variableVisitor.ParameterValues, variableVisitor.Parameters);
                base.QueryCache.AddQuery(cacheContext, executor, countExpression, queryContext.EntryFactory);
                parameterValues = variableVisitor.ParameterValues;
            }
            else
            {
                executor = (InMemoryExecutor)queryCacheItem.Query;
                queryContext.EntryFactory = queryCacheItem.EntryFactory;
                countExpression           = queryCacheItem.CountExpression;
                parameterValues           = cacheContext.ParameterValues;
            }

            if (!queryContext.IsQueryCount())
            {
                countExpression = null;
            }

            executor.Wait();
            executor.SetDataContext(dataContext);
            for (int i = 0; i < parameterValues.Count; i++)
            {
                executor[parameterValues[i].ParameterName] = parameterValues[i].ParameterValue;
            }
            return(executor);
        }
Ejemplo n.º 15
0
 public OeQueryCacheItem(Object query, MethodCallExpression?countExpression, OeEntryFactory?entryFactory)
 {
     Query           = query;
     CountExpression = countExpression;
     EntryFactory    = entryFactory;
 }
Ejemplo n.º 16
0
        public void AddQuery(OeCacheContext cacheContext, Object query, MethodCallExpression?countExpression, OeEntryFactory?entryFactory)
        {
            var queryCacheItem = new OeQueryCacheItem(query, countExpression, entryFactory);

            _cache.TryAdd(cacheContext, queryCacheItem);
        }