示例#1
0
        /// <summary>Sorts a query like a SQL ORDER BY clause does.</summary>
        /// <param name="source">Original source for query.</param>
        /// <param name="orderingInfo">Ordering definition to compose.</param>
        /// <returns>The composed query.</returns>
        internal static Expression OrderBy(Expression source, OrderingInfo orderingInfo)
        {
            Debug.Assert(source != null, "source != null");
            Debug.Assert(orderingInfo != null, "orderingInfo != null");

            Expression queryExpr  = source;
            bool       useOrderBy = true;

            foreach (OrderingExpression o in orderingInfo.OrderingExpressions)
            {
                LambdaExpression selectorLambda = (LambdaExpression)o.Expression;

                Type selectorType = selectorLambda.Body.Type;
                Debug.Assert(selectorType != null, "type != null");

                // ensure either the expression type is orderable (ie, primitive) or its an open expression.
                if (!WebUtil.IsPrimitiveType(selectorType) && !OpenTypeMethods.IsOpenExpression(selectorLambda.Body))
                {
                    throw DataServiceException.CreateBadRequestError(Strings.RequestQueryParser_OrderByDoesNotSupportType(WebUtil.GetTypeName(selectorType)));
                }

                if (useOrderBy)
                {
                    queryExpr = o.IsAscending ? queryExpr.QueryableOrderBy(selectorLambda) : queryExpr.QueryableOrderByDescending(selectorLambda);
                }
                else
                {
                    queryExpr = o.IsAscending ? queryExpr.QueryableThenBy(selectorLambda) : queryExpr.QueryableThenByDescending(selectorLambda);
                }

                useOrderBy = false;
            }

            return(queryExpr);
        }
示例#2
0
        /// <summary>Finds the best methods for the specified arguments given a candidate method enumeration.</summary>
        /// <param name="methods">Enumerable object for candidate methods.</param>
        /// <param name="args">Argument expressions to match.</param>
        /// <param name="method">Best matched method.</param>
        /// <returns>The number of "best match" methods.</returns>
        private int FindBestMethod(IEnumerable <MethodBase> methods, Expression[] args, out MethodBase method)
        {
            MethodData[] applicable = this.FindApplicableMethods(methods, args);
            if (applicable.Length > 1)
            {
                applicable = FindBestApplicableMethods(applicable, args);
            }

            int result = applicable.Length;

            method = null;
            if (applicable.Length == 1)
            {
                // If we started off with all non-OpenType expressions and end with all-OpenType
                // expressions, we've been too aggresive - the transition from non-open-types
                // to open types should initially happen only as a result of accessing open properties.
                MethodData md = applicable[0];
                bool       originalArgsDefined = true;
                bool       promotedArgsOpen    = true;
                for (int i = 0; i < args.Length; i++)
                {
                    originalArgsDefined = originalArgsDefined && !OpenTypeMethods.IsOpenPropertyExpression(args[i]);
                    promotedArgsOpen    = promotedArgsOpen && md.Parameters[i].ParameterType == typeof(object);
                    args[i]             = md.Args[i];
                }

                method = (originalArgsDefined && promotedArgsOpen) ? null : md.MethodBase;
                result = (method == null) ? 0 : 1;
            }
            else if (applicable.Length > 1)
            {
                // We may have the case for operators (which C# doesn't) in which we have a nullable operand
                // and a non-nullable operand. We choose to convert the one non-null operand to nullable in that
                // case (the binary expression will lift to null).
                if (args.Length == 2 && applicable.Length == 2 &&
                    WebUtil.GetNonNullableType(applicable[0].Parameters[0].ParameterType) ==
                    WebUtil.GetNonNullableType(applicable[1].Parameters[0].ParameterType))
                {
                    MethodData nullableMethod =
                        WebUtil.TypeAllowsNull(applicable[0].Parameters[0].ParameterType) ?
                        applicable[0] :
                        applicable[1];
                    args[0] = nullableMethod.Args[0];
                    args[1] = nullableMethod.Args[1];
                    return(this.FindBestMethod(methods, args, out method));
                }
            }

            return(result);
        }
示例#3
0
 public void OpenCollectionTranslatorShouldConvertAllWithBody()
 {
     this.TestLambda <AllNode, Customer, bool>(this.OpenCollectionNavigationFromParameter("o", "OpenOtherCustomers"), "i", Constant(false), o => OpenTypeMethods.GetCollectionValue(o, "OpenOtherCustomers").All(i => false));
 }
示例#4
0
 public void TranslatorShouldConvertOpenCollectionProperty()
 {
     this.TestOpenCollectionProperty <Customer, object>(EntityParameter <Customer>("c"), "Foo", c => OpenTypeMethods.GetCollectionValue(c, "Foo"));
 }