/// <summary>
            /// Unify all ordering expressions into a single order expression
            /// </summary>
            private void FlattenOrderExpressions()
            {
                List <ServiceQueryPart> newList   = new List <ServiceQueryPart>();
                ServiceQueryPart        orderPart = null;

                foreach (ServiceQueryPart part in this._queryParts)
                {
                    if (part.QueryOperator.StartsWith("orderby", StringComparison.Ordinal))
                    {
                        orderPart = part;
                    }

                    if (part.QueryOperator.StartsWith("thenby", StringComparison.Ordinal))
                    {
                        // accumulate secondary ordering expressions
                        orderPart.Expression += ", " + part.Expression;
                    }
                    else
                    {
                        newList.Add(part);
                    }
                }

                this._queryParts = newList;
            }
            protected override Expression VisitMethodCall(MethodCallExpression m)
            {
                ServiceQueryPart holdPart        = this._currPart;
                StringBuilder    holdPartBuilder = this._currPartBuilder;

                string methodName = CultureInfo.InvariantCulture.TextInfo.ToLower(m.Method.Name);

                if (IsSequenceOperatorCall(m))
                {
                    if (methodName == "where" || methodName == "orderby" || methodName == "orderbydescending" || methodName == "skip" ||
                        methodName == "take" || methodName == "thenby" || methodName == "thenbydescending")
                    {
                        this._currPart               = new ServiceQueryPart();
                        this._currPartBuilder        = new StringBuilder();
                        this._currPart.QueryOperator = methodName;
                        this._queryParts.Add(this._currPart);
                    }
                    else if (methodName == "select")
                    {
                        // if the selection specified is anything other than an
                        // empty selector, throw an exception. I.e. only Select(p => p)
                        // is supported.
                        bool       isEmptySelection = false;
                        Expression selector         = m.Arguments[1];
                        if (selector.NodeType == ExpressionType.Quote)
                        {
                            LambdaExpression lex = (LambdaExpression)((UnaryExpression)m.Arguments[1]).Operand;
                            isEmptySelection = (lex.Body.NodeType == ExpressionType.Parameter) &&
                                               (lex.Parameters.Single() == lex.Body);
                        }
                        if (!isEmptySelection)
                        {
                            throw new NotSupportedException(Resources.QuerySerialization_ProjectionsNotSupported);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.QuerySerialization_UnsupportedQueryOperator, m.Method.Name));
                    }

                    Expression obj = this.Visit(m.Object);
                    IEnumerable <Expression> args = this.Visit(m.Arguments);
                    if (obj != m.Object || args != m.Arguments)
                    {
                        return(Expression.Call(obj, m.Method, args));
                    }

                    // post processing
                    if (methodName == "orderbydescending" || methodName == "thenbydescending")
                    {
                        if (methodName == "orderbydescending")
                        {
                            this._currPart.QueryOperator = "orderby";
                        }
                        else
                        {
                            this._currPart.QueryOperator = "thenby";
                        }

                        this._currPartBuilder.Append(" desc");
                    }
                }
                else if (m.Method.DeclaringType == typeof(Enum) && m.Method.Name == "HasFlag")
                {
                    // Serialize (p => p.enumProp.HasFlag( EnumType.A)) into "(it.enumProp has EnumType.A)"

                    this._currPartBuilder.Append("(");
                    this.Visit(m.Object);

                    // We could convert it to an int here if possible, otherwise we will do it anyway on the server
                    //this.Visit(Expression.Convert(m.Object, typeof(int)));
                    this._currPartBuilder.Append(" has ");

                    // We could convert it to an int here if possible, otherwise we will do it anyway on the server
                    //this.Visit(Expression.Convert(m.Arguments[0], typeof(int)));
                    this.Visit(m.Arguments[0]);

                    this._currPartBuilder.Append(")");
                }
                else
                {
                    // Ensure that the method is accessible
                    // Only methods on supported predefined types are allowed
                    VerifyMethodAccessibility(m);

                    if (m.Method.IsStatic)
                    {
                        this._currPartBuilder.Append(m.Method.DeclaringType.Name);
                    }
                    else
                    {
                        this.Visit(m.Object);
                    }
                    if (m.Object == null || m.Object.NodeType != ExpressionType.Parameter)
                    {
                        // for all member accesses other than those directly off of
                        // our query parameter, we need to append a dot
                        this._currPartBuilder.Append(".");
                    }
                    this._currPartBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}(", m.Method.Name);
                    this.VisitMethodParameters(m.Arguments);
                    this._currPartBuilder.Append(")");
                }

                if (this._currPart != null)
                {
                    this._currPart.Expression = this._currPartBuilder.ToString();
                }
                this._currPart        = holdPart;
                this._currPartBuilder = holdPartBuilder;

                return(m);
            }