This defines some context information used to perform query composition.
示例#1
0
        /// <summary>
        /// Generates a dictionary with property name and property values specified in the skiptoken value.
        /// </summary>
        /// <param name="value">The skiptoken string value.</param>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
        /// <returns>Dictionary with property name and property value in the skiptoken value.</returns>
        internal static IDictionary <string, object> PopulatePropertyValuePairs(string value, ODataQueryContext context)
        {
            Contract.Assert(context != null);

            IDictionary <string, object> propertyValuePairs = new Dictionary <string, object>();
            IList <string> keyValuesPairs = ParseValue(value, CommaDelimiter);

            IEdmStructuredType type = context.ElementType as IEdmStructuredType;

            Debug.Assert(type != null);

            foreach (string pair in keyValuesPairs)
            {
                string[] pieces = pair.Split(new char[] { propertyDelimiter }, 2);
                if (pieces.Length > 1 && !String.IsNullOrWhiteSpace(pieces[0]))
                {
                    object propValue = null;

                    IEdmTypeReference propertyType = null;
                    IEdmProperty      property     = type.FindProperty(pieces[0]);
                    if (property != null)
                    {
                        propertyType = property.Type;
                    }

                    propValue = ODataUriUtils.ConvertFromUriLiteral(pieces[1], ODataVersion.V401, context.Model, propertyType);
                    propertyValuePairs.Add(pieces[0], propValue);
                }
                else
                {
                    throw new ODataException(Error.Format(SRResources.SkipTokenParseError, value));
                }
            }

            return(propertyValuePairs);
        }
示例#2
0
        /// <summary>
        /// Core logic for applying the query option to the IQueryable.
        /// </summary>
        /// <param name="query">The original <see cref="IQueryable"/>.</param>
        /// <param name="querySettings">Query setting used for validating the query option.</param>
        /// <param name="orderByNodes">OrderBy information required to correctly apply the query option for default implementation.</param>
        /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
        /// <param name="skipTokenRawValue">The raw string value of the skiptoken query parameter.</param>
        /// <returns></returns>
        private static IQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings, IList <OrderByNode> orderByNodes, ODataQueryContext context, string skipTokenRawValue)
        {
            Contract.Assert(query != null);
            Contract.Assert(context.ElementClrType != null);

            IDictionary <string, OrderByDirection> directionMap;

            if (orderByNodes != null)
            {
                directionMap =
                    orderByNodes.OfType <OrderByPropertyNode>().ToDictionary(node => node.Property.Name, node => node.Direction);
            }
            else
            {
                directionMap = new Dictionary <string, OrderByDirection>();
            }

            IDictionary <string, object> propertyValuePairs = PopulatePropertyValuePairs(skipTokenRawValue, context);

            if (propertyValuePairs.Count == 0)
            {
                throw Error.InvalidOperation("Unable to get property values from the skiptoken value.");
            }

            ExpressionBinderBase binder = context.GetFilterBinder(querySettings);
            bool parameterizeConstant   = querySettings.EnableConstantParameterization;
            ParameterExpression param   = Expression.Parameter(context.ElementClrType);

            Expression where = null;

            /* We will create a where lambda of the following form -
             * Where (Prop1>Value1)
             * OR (Prop1=Value1 AND Prop2>Value2)
             * OR (Prop1=Value1 AND Prop2=Value2 AND Prop3>Value3)
             * and so on...
             * Adding the first true to simplify implementation.
             */
            Expression lastEquality  = null;
            bool       firstProperty = true;

            foreach (KeyValuePair <string, object> item in propertyValuePairs)
            {
                string           key      = item.Key;
                MemberExpression property = Expression.Property(param, key);
                object           value    = item.Value;

                Expression     compare   = null;
                ODataEnumValue enumValue = value as ODataEnumValue;
                if (enumValue != null)
                {
                    value = enumValue.Value;
                }

                Expression constant = parameterizeConstant ? LinqParameterContainer.Parameterize(value.GetType(), value) : Expression.Constant(value);
                if (directionMap.ContainsKey(key) && directionMap[key] == OrderByDirection.Descending)
                {
                    compare = binder.CreateBinaryExpression(BinaryOperatorKind.LessThan, property, constant, true);
                }
                else
                {
                    compare = binder.CreateBinaryExpression(BinaryOperatorKind.GreaterThan, property, constant, true);
                }

                if (firstProperty)
                {
                    lastEquality  = binder.CreateBinaryExpression(BinaryOperatorKind.Equal, property, constant, true);
                    where         = compare;
                    firstProperty = false;
                }
                else
                {
                    Expression condition = Expression.AndAlso(lastEquality, compare);
                    where        = Expression.OrElse(where, condition);
                    lastEquality = Expression.AndAlso(lastEquality, binder.CreateBinaryExpression(BinaryOperatorKind.Equal, property, constant, true));
                }
            }

            Expression whereLambda = Expression.Lambda(where, param);

            return(ExpressionHelpers.Where(query, whereLambda, query.ElementType));
        }