/// <summary> /// Apply the ETag to the given IQueryable. /// </summary> /// <param name="query">The original <see cref="IQueryable"/>.</param> /// <returns>The new <see cref="IQueryable"/> after the ETag has been applied to.</returns> public virtual IQueryable ApplyTo(IQueryable query) { Type type = EntityType; ParameterExpression param = Expression.Parameter(type); Expression where = null; foreach (KeyValuePair <string, object> item in ConcurrencyProperties) { MemberExpression name = Expression.Property(param, item.Key); object itemValue = item.Value; Expression value = itemValue != null ? LinqParameterContainer.Parameterize(itemValue.GetType(), itemValue) : Expression.Constant(value: null); BinaryExpression equal = Expression.Equal(name, value); where = where == null ? equal : Expression.AndAlso(where, equal); } if (where == null) { return(query); } if (IsIfNoneMatch) { where = Expression.Not(where); } Expression whereLambda = Expression.Lambda(where, param); return(ExpressionHelpers.Where(query, whereLambda, type)); }
protected override Expression VisitConstant(ConstantExpression node) { if (node.Value == null) { Out("null"); } else { LinqParameterContainer container = node.Value as LinqParameterContainer; string stringValue; if (container != null) { stringValue = container.Property as string; if (stringValue != null) { Out("\"" + stringValue + "\""); } else { stringValue = String.Format(CultureInfo.InvariantCulture, "{0}", container.Property); Out(stringValue); } } else { stringValue = String.Format(CultureInfo.InvariantCulture, "{0}", node.Value); Out(stringValue); } } return(node); }
public void Parameterize_ProducesPropertyAccessOnConstant(object value) { Expression expr = LinqParameterContainer.Parameterize(value.GetType(), value); LinqParameterContainer parameterizedValue = ((expr as MemberExpression).Expression as ConstantExpression).Value as LinqParameterContainer; Assert.Equal(value, parameterizedValue.Property); }
public static IQueryable Take(IQueryable query, int count, Type type, bool parameterize) { MethodInfo takeMethod = ExpressionHelperMethods.QueryableTakeGeneric.MakeGenericMethod(type); Expression takeValueExpression = parameterize ? LinqParameterContainer.Parameterize(typeof(int), count) : Expression.Constant(count); Expression takeQuery = Expression.Call(null, takeMethod, new[] { query.Expression, takeValueExpression }); return(query.Provider.CreateQuery(takeQuery)); }
public static Expression Parameterize(Type type, object value) { // () => new LinqParameterContainer(constant).Property // instead of returning a constant expression node, wrap that constant in a class the way compiler // does a closure, so that EF can parameterize the constant (resulting in better performance due to expression translation caching). LinqParameterContainer containedValue = LinqParameterContainer.Create(type, value); return(Expression.Property(Expression.Constant(containedValue), "TypedProperty")); }
public static IQueryable Skip(IQueryable query, int count, Type type, bool parameterize) { MethodInfo skipMethod = ExpressionHelperMethods.QueryableSkipGeneric.MakeGenericMethod(type); Expression skipValueExpression = parameterize ? LinqParameterContainer.Parameterize(typeof(int), count) : Expression.Constant(count); Expression skipQuery = Expression.Call(null, skipMethod, new[] { query.Expression, skipValueExpression }); var createMethod = ExpressionHelperMethods.CreateQueryGeneric.MakeGenericMethod(type); return(createMethod.Invoke(query.Provider, new[] { skipQuery }) as IQueryable); }
public static Expression Take(Expression source, int count, Type elementType, bool parameterize) { MethodInfo takeMethod; if (typeof(IQueryable).IsAssignableFrom(source.Type)) { takeMethod = ExpressionHelperMethods.QueryableTakeGeneric.MakeGenericMethod(elementType); } else { takeMethod = ExpressionHelperMethods.EnumerableTakeGeneric.MakeGenericMethod(elementType); } Expression takeValueExpression = parameterize ? LinqParameterContainer.Parameterize(typeof(int), count) : Expression.Constant(count); Expression takeQuery = Expression.Call(null, takeMethod, new[] { source, takeValueExpression }); return(takeQuery); }
public static Expression Skip(Expression source, int count, Type type, bool parameterize) { MethodInfo skipMethod; if (typeof(IQueryable).IsAssignableFrom(source.Type)) { skipMethod = ExpressionHelperMethods.QueryableSkipGeneric.MakeGenericMethod(type); } else { skipMethod = ExpressionHelperMethods.EnumerableSkipGeneric.MakeGenericMethod(type); } Expression skipValueExpression = parameterize ? LinqParameterContainer.Parameterize(typeof(int), count) : Expression.Constant(count); Expression skipQuery = Expression.Call(null, skipMethod, new[] { source, skipValueExpression }); return(skipQuery); }
/// <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) { if (query == null) { throw Error.ArgumentNull(nameof(query)); } if (context.ElementClrType == null) { throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo"); } 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)); }