예제 #1
0
 private void Compile()
 {
     if (_query == null)
     {
         _query = SnExpression.BuildQuery(_queryable.Expression, typeof(T), _queryable.ContextPath, _queryable.ChildrenDefinition);
     }
 }
예제 #2
0
 private void Compile()
 {
     if (_query == null)
     {
         var query = SnExpression.BuildQuery(_queryable.Expression, typeof(T), _queryable.ContextPath, _queryable.ChildrenDefinition);
         query.AddAndClause(SnExpression.GetPathPredicate(_queryable.ContextPath, _queryable.SubTree));
         _query = query;
     }
 }
예제 #3
0
        // ==================================================================================================================================================
        private ContentSet <Q> Clone <Q>(Expression expression)
        {
            if (typeof(Content) != typeof(Q))
            {
                this.TypeFilter = typeof(Q);
            }
            if (typeof(Q) == typeof(Content) || typeof(Node).IsAssignableFrom(typeof(Q)))
            {
                return new ContentSet <Q>(expression, this.ChildrenDefinition.Clone(), this.ContextPath)
                       {
                           CountOnlyEnabled   = this.CountOnlyEnabled,
                           HeadersOnlyEnabled = this.HeadersOnlyEnabled,
                           TypeFilter         = this.TypeFilter
                       }
            }
            ;
            if (expression is MethodCallExpression callExpr)
            {
                var lastMethodName = callExpr.Method.Name;

                throw SnExpression.CallingAsEnunerableExpectedError(lastMethodName);
            }
            throw SnExpression.CallingAsEnunerableExpectedError(expression);
        }
예제 #4
0
        // ==================================================================================================================================================
        public SnQuery GetCompiledQuery()
        {
            var q = SnExpression.BuildQuery(this.Expression, typeof(T), this.ContextPath, this.ChildrenDefinition);

            return(q);
        }
예제 #5
0
        public virtual TResult Execute <TResult>(Expression expression)
        {
            var count = 0;

            // in case there is a predefined list of nodes, we do not execute a query (but we still need to build it)
            if (!this.ExecuteQuery)
            {
                count = ChildrenDefinition.BaseCollection.Count();
            }

            var query = SnExpression.BuildQuery(expression, typeof(T), this.ContextPath, this.ChildrenDefinition, out var elementSelection);

            if (TracingEnabled)
            {
                TraceLog.Append("Expression: ").AppendLine(expression.ToString());
                TraceLog.Append("Query:      ").AppendLine(query.ToString());
                TraceLog.AppendLine("--------------");
            }
            var result = this.ExecuteQuery ? query.Execute(SnQueryContext.CreateDefault()) : null;

            if (query.CountOnly)
            {
                if (this.ExecuteQuery)
                {
                    count = result.TotalCount;
                }

                if (query.ExistenceOnly)
                {
                    return((TResult)Convert.ChangeType(count > 0, typeof(TResult)));
                }
                return((TResult)Convert.ChangeType(count, typeof(TResult)));
            }

            if (this.ExecuteQuery)
            {
                count = result.TotalCount;
            }

            if (count == 0)
            {
                if (query.ThrowIfEmpty)
                {
                    if (elementSelection == "elementat")
                    {
                        // ReSharper disable once NotResolvedInText
                        throw new ArgumentOutOfRangeException("Index was out of range.");
                    }
                    else
                    {
                        throw new InvalidOperationException("Sequence contains no elements.");
                    }
                }
                return(default(TResult));
            }

            if (typeof(Node).IsAssignableFrom(typeof(TResult)))
            {
                if (ExecuteQuery)
                {
                    return((TResult)Convert.ChangeType(Node.LoadNode(result.Hits.First()), typeof(TResult)));
                }
                return((TResult)Convert.ChangeType(ChildrenDefinition.BaseCollection.First(), typeof(TResult)));
            }

            switch (elementSelection)
            {
            case "first":
                return(ExecuteQuery
                        ? (TResult)Convert.ChangeType(Content.Load(result.Hits.FirstOrDefault()), typeof(TResult))
                        : (TResult)Convert.ChangeType(Content.Create(ChildrenDefinition.BaseCollection.FirstOrDefault()), typeof(TResult)));

            case "last":
                return(ExecuteQuery
                        ? (TResult)Convert.ChangeType(Content.Load(result.Hits.LastOrDefault()), typeof(TResult))
                        : (TResult)Convert.ChangeType(Content.Create(ChildrenDefinition.BaseCollection.LastOrDefault()), typeof(TResult)));

            case "single":
                return(ExecuteQuery
                        ? (TResult)Convert.ChangeType(Content.Load(result.Hits.SingleOrDefault()), typeof(TResult))
                        : (TResult)Convert.ChangeType(Content.Create(ChildrenDefinition.BaseCollection.SingleOrDefault()), typeof(TResult)));

            case "elementat":
                var any = ExecuteQuery ? result.Hits.Any() : ChildrenDefinition.BaseCollection.Any();
                if (!any)
                {
                    if (query.ThrowIfEmpty)
                    {
                        // ReSharper disable once NotResolvedInText
                        throw new ArgumentOutOfRangeException("Index was out of range.");
                    }
                    else
                    {
                        return(default(TResult));
                    }
                }
                return(ExecuteQuery
                        ? (TResult)Convert.ChangeType(Content.Load(result.Hits.FirstOrDefault()), typeof(TResult))
                        : (TResult)Convert.ChangeType(Content.Create(ChildrenDefinition.BaseCollection.FirstOrDefault()), typeof(TResult)));

            default:
                throw new SnNotSupportedException();
            }
        }
예제 #6
0
 internal static SnQuery GetSnQuery(Expression expr, bool autoFiltersEnabled, bool lifespanEnabled, ChildrenDefinition childrenDef, string contextPath)
 {
     return(SnExpression.BuildQuery(expr, typeof(T), contextPath, childrenDef));
 }
예제 #7
0
        public virtual TResult Execute <TResult>(System.Linq.Expressions.Expression expression)
        {
            int count = 0;

            // in case there is a predefined list of nodes, we do not execute a query (but we still need to build it)
            if (!this.ExecuteQuery)
            {
                count = ChildrenDefinition.BaseCollection.Count();
            }

            var query = SnExpression.BuildQuery(expression, typeof(T), this.ContextPath, this.ChildrenDefinition);

            if (TracingEnabled)
            {
                TraceLog.Append("Expression: ").AppendLine(expression.ToString());
                TraceLog.Append("Query:      ").AppendLine(query.ToString());
                TraceLog.AppendLine("--------------");
            }
            var result = this.ExecuteQuery ? query.Execute() : null;

            if (query.CountOnly)
            {
                if (this.ExecuteQuery)
                {
                    count = query.TotalCount;
                }

                if (query.ExistenceOnly)
                {
                    return((TResult)Convert.ChangeType(count > 0, typeof(TResult)));
                }
                else
                {
                    return((TResult)Convert.ChangeType(count, typeof(TResult)));
                }
            }
            if (this.ExecuteQuery)
            {
                count = result.Count();
            }

            if (count == 0)
            {
                if (query.ThrowIfEmpty)
                {
                    throw new InvalidOperationException("Sequence contains no elements.");
                }
                return(default(TResult));
            }
            if (count == 1)
            {
                if (typeof(Node).IsAssignableFrom(typeof(TResult)))
                {
                    if (this.ExecuteQuery)
                    {
                        return((TResult)Convert.ChangeType(Node.LoadNode(result.First().NodeId), typeof(TResult)));
                    }
                    return((TResult)Convert.ChangeType(ChildrenDefinition.BaseCollection.First(), typeof(TResult)));
                }
                if (this.ExecuteQuery)
                {
                    return((TResult)Convert.ChangeType(Content.Load(result.First().NodeId), typeof(TResult)));
                }
                return((TResult)Convert.ChangeType(Content.Create(ChildrenDefinition.BaseCollection.First()), typeof(TResult)));
            }

            throw new NotImplementedException("SnLinq: ContentSet.Execute<TResult>");
        }
예제 #8
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            Trace(MethodBase.GetCurrentMethod(), node);
            Expression visited = null;

            try
            {
                visited = base.VisitMethodCall(node);
            }
            catch (SnNotSupportedException e)
            {
                throw SnExpression.CallingAsEnunerableExpectedError(node.Method.Name, e);
            }

            if (!(visited is MethodCallExpression methodCallExpr))
            {
                throw new NotSupportedException("#VisitMethodCall if visited is not null");
            }

            var methodName = methodCallExpr.Method.Name;

            switch (methodName)
            {
            case "OfType":
            // Do nothing. Type of expression has been changed so a TypeIs predicate will be created.
            case "Where":
                // do nothing
                break;

            case "Take":
                var topExpr = GetArgumentAsConstant(methodCallExpr, 1);
                this.Top = (int)topExpr.Value;
                break;

            case "Skip":
                var skipExpr = GetArgumentAsConstant(methodCallExpr, 1);
                this.Skip = (int)skipExpr.Value;
                break;

            case "LongCount":
            case "Count":
                if (methodCallExpr.Arguments.Count == 2)
                {
                    if (_predicates.Count > 1)     // There is Where in the main expression
                    {
                        CombineTwoPredicatesOnStack();
                    }
                }
                this.CountOnly = true;
                break;

            case "ThenBy":
            case "OrderBy":
                Sort.Add(CreateSortInfoFromExpr(node, false));
                break;

            case "ThenByDescending":
            case "OrderByDescending":
                Sort.Add(CreateSortInfoFromExpr(node, true));
                break;

            case "StartsWith":
                var startsWithExpr = GetArgumentAsConstant(methodCallExpr, 0);
                var startsWithArg  = (string)startsWithExpr.Value;
                BuildWildcardPredicate(GetPropertyName(methodCallExpr.Object), WildcardPosition.AtEnd, startsWithArg);
                break;

            case "EndsWith":
                var endsWithExpr = GetArgumentAsConstant(methodCallExpr, 0);
                var endsWithArg  = (string)endsWithExpr.Value;
                BuildWildcardPredicate(GetPropertyName(methodCallExpr.Object), WildcardPosition.AtStart, endsWithArg);
                break;

            case "Contains":
                var arg0 = methodCallExpr.Arguments[0];
                if (arg0 is ConstantExpression constantExpr)
                {
                    if (constantExpr.Type != typeof(string))
                    {
                        throw new NotSupportedException(
                                  $"Calling Contains on an instance of type {constantExpr.Type} is not supported. Allowed types: string, IEnumerable<Node>.");
                    }
                    var containsArg = (string)constantExpr.Value;
                    BuildWildcardPredicate(GetPropertyName(methodCallExpr.Object), WildcardPosition.AtStartAndEnd, containsArg);
                    break;
                }
                if (arg0 is MemberExpression memberExpr)
                {
                    if (memberExpr.Type != typeof(IEnumerable <Node>))
                    {
                        throw NotSupportedException(node, "#2");
                    }
                    if (!(methodCallExpr.Arguments[1] is ConstantExpression rightConstant))
                    {
                        throw NotSupportedException(node, "#1");
                    }
                    var nodeValue = (Node)rightConstant.Value;
                    BuildTextPredicate(memberExpr.Member.Name, nodeValue);
                    break;
                }
                throw NotSupportedException(node, "#3");

            case "FirstOrDefault":
            case "First":
                ElementSelection  = "first";
                this.Top          = 1;
                this.ThrowIfEmpty = methodName == "First";
                if (methodCallExpr.Arguments.Count == 2)
                {
                    if (_predicates.Count > 1)
                    {
                        CombineTwoPredicatesOnStack();
                    }
                }
                break;

            case "SingleOrDefault":
            case "Single":
                ElementSelection  = "single";
                this.ThrowIfEmpty = methodName == "Single";
                if (methodCallExpr.Arguments.Count == 2)
                {
                    if (_predicates.Count > 1)
                    {
                        CombineTwoPredicatesOnStack();
                    }
                }
                break;

            case "LastOrDefault":
            case "Last":
                ElementSelection  = "last";
                this.ThrowIfEmpty = methodName == "Last";
                if (methodCallExpr.Arguments.Count == 2)
                {
                    if (_predicates.Count > 1)
                    {
                        CombineTwoPredicatesOnStack();
                    }
                }
                break;

            case "ElementAtOrDefault":
            case "ElementAt":
                ElementSelection  = "elementat";
                this.ThrowIfEmpty = methodName == "ElementAt";
                var constExpr = GetArgumentAsConstant(methodCallExpr, 1);
                var index     = Convert.ToInt32(constExpr.Value);
                this.Skip = index;
                this.Top  = 1;
                break;

            case "Any":
                ElementSelection   = "first";
                this.CountOnly     = true;
                this.ExistenceOnly = true;
                this.Top           = 1;
                if (methodCallExpr.Arguments.Count == 2)
                {
                    if (_predicates.Count > 1)
                    {
                        CombineTwoPredicatesOnStack();
                    }
                }
                break;

            case "Type":
                var typeExpr = GetArgumentAsConstant(methodCallExpr, 0);
                BuildTextPredicate("Type", (string)typeExpr.Value);
                break;

            case "TypeIs":
                var typeIsExpr = GetArgumentAsConstant(methodCallExpr, 0);
                BuildTextPredicate("TypeIs", (string)(typeIsExpr).Value);
                break;

            case "get_Item":
                if (!(methodCallExpr.Object is ParameterExpression))
                {
                    throw new NotSupportedException("#get_Item");
                }
                break;

            case "startswith":
            {
                var fieldName      = GetPropertyName(methodCallExpr.Arguments[0]);
                var startswithExpr = GetArgumentAsConstant(methodCallExpr, 1);
                var arg            = (string)startswithExpr.Value;
                BuildWildcardPredicate(fieldName, WildcardPosition.AtEnd, arg);
                break;
            }

            case "endswith":
            {
                var fieldName    = GetPropertyName(methodCallExpr.Arguments[0]);
                var endswithExpr = GetArgumentAsConstant(methodCallExpr, 1);
                var arg          = (string)endswithExpr.Value;
                BuildWildcardPredicate(fieldName, WildcardPosition.AtStart, arg);
                break;
            }

            case "substringof":
            {
                var fieldName       = GetPropertyName(methodCallExpr.Arguments[1]);
                var substringofExpr = GetArgumentAsConstant(methodCallExpr, 0);
                var arg             = (string)substringofExpr.Value;
                BuildWildcardPredicate(fieldName, WildcardPosition.AtStartAndEnd, arg);
                break;
            }

            case "isof":
            {
                var isofExpr = GetArgumentAsConstant(methodCallExpr, 1);
                BuildTextPredicate("TypeIs", (string)(isofExpr).Value);
                break;
            }

            case "InFolder":
            {
                var infolderexpr = GetArgumentAsConstant(methodCallExpr, 0);
                var folder       = infolderexpr.Value;
                BuildTextPredicate("InFolder", GetPath(folder, "InFolder"));
                break;
            }

            case "InTree":
            {
                var intreeexpr = GetArgumentAsConstant(methodCallExpr, 0);
                var folder     = intreeexpr.Value;
                BuildTextPredicate("InTree", GetPath(folder, "InTree"));
                break;
            }

            case "GetType":
            {
                if (methodCallExpr.Object is MemberExpression member && member.Member == typeof(Content).GetProperty("ContentHandler"))
                {
                    _predicates.Push(new ContentHandlerGetTypePredicate());
                }