public static Expression DateTimeOffsetToDateTime(Expression expression, TimeZoneInfo timeZoneInfo, ODataQuerySettings settings) { var unaryExpression = expression as UnaryExpression; if (unaryExpression != null) { if (Nullable.GetUnderlyingType(unaryExpression.Type) == unaryExpression.Operand.Type) { // this is a cast from T to Nullable<T> which is redundant. expression = unaryExpression.Operand; } } var parameterizedConstantValue = ExtractParameterizedConstant(expression); var dto = parameterizedConstantValue as DateTimeOffset?; if (dto != null) { if (settings.EnableConstantParameterization) { return(LinqParameterContainer.Parameterize(typeof(DateTime), EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo))); } else { return(Expression.Constant(EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo), typeof(DateTime))); } } return(expression); }
// Extract the constant that would have been encapsulated into LinqParameterContainer if this // expression represents it else return null. internal static object ExtractParameterizedConstant(Expression expression) { if (expression.NodeType == ExpressionType.MemberAccess) { MemberExpression memberAccess = expression as MemberExpression; Contract.Assert(memberAccess != null); PropertyInfo propertyInfo = memberAccess.Member as PropertyInfo; if (propertyInfo != null && propertyInfo.GetMethod.IsStatic) { return(propertyInfo.GetValue(new object())); } if (memberAccess.Expression.NodeType == ExpressionType.Constant) { ConstantExpression constant = memberAccess.Expression as ConstantExpression; Contract.Assert(constant != null); Contract.Assert(constant.Value != null); LinqParameterContainer value = constant.Value as LinqParameterContainer; Contract.Assert(value != null, "Constants are already embedded into LinqParameterContainer"); return(value.Property); } } return(null); }
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 }); return(query.Provider.CreateQuery(skipQuery)); }
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 IQueryable Bind(IQueryable query) { PreprocessQuery(query); // compute(X add Y as Z, A mul B as C) adds new properties to the output // Should return following expression // .Select($it => new ComputeWrapper<T> { // Instance = $it, // ModelID = 'Guid', // Container => new AggregationPropertyContainer() { // Name = "X", // Value = $it.X + $it.Y, // Next = new LastInChain() { // Name = "C", // Value = $it.A * $it.B // } // }) List <MemberAssignment> wrapperTypeMemberAssignments = new List <MemberAssignment>(); // Set Instance property var wrapperProperty = this.ResultClrType.GetProperty("Instance"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, this.LambdaParameter)); var properties = new List <NamedPropertyExpression>(); foreach (var computeExpression in this._transformation.Expressions) { properties.Add(new NamedPropertyExpression(Expression.Constant(computeExpression.Alias), CreateComputeExpression(computeExpression))); } // Initialize property 'ModelID' on the wrapper class. // source = new Wrapper { ModelID = 'some-guid-id' } wrapperProperty = this.ResultClrType.GetProperty("ModelID"); var wrapperPropertyValueExpression = QuerySettings.EnableConstantParameterization ? LinqParameterContainer.Parameterize(typeof(string), _modelID) : Expression.Constant(_modelID); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, wrapperPropertyValueExpression)); // Set new compute properties wrapperProperty = ResultClrType.GetProperty("Container"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, AggregationPropertyContainer.CreateNextNamedPropertyContainer(properties))); var initilizedMember = Expression.MemberInit(Expression.New(ResultClrType), wrapperTypeMemberAssignments); var selectLambda = Expression.Lambda(initilizedMember, this.LambdaParameter); var result = ExpressionHelpers.Select(query, selectLambda, this.ElementType); return(result); }
public IQueryable Bind(IQueryable query) { PreprocessQuery(query); // compute(X add Y as Z, A mul B as C) adds new properties to the output // Should return following expression // .Select($it => new ComputeWrapper<T> { // Instance = $it, // Model = parametrized(IEdmModel), // Container => new AggregationPropertyContainer() { // Name = "X", // Value = $it.X + $it.Y, // Next = new LastInChain() { // Name = "C", // Value = $it.A * $it.B // } // }) List <MemberAssignment> wrapperTypeMemberAssignments = new List <MemberAssignment>(); // Set Instance property var wrapperProperty = this.ResultClrType.GetProperty("Instance"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, this.LambdaParameter)); var properties = new List <NamedPropertyExpression>(); foreach (var computeExpression in this._transformation.Expressions) { properties.Add(new NamedPropertyExpression(Expression.Constant(computeExpression.Alias), CreateComputeExpression(computeExpression))); } // Initialize property 'Model' on the wrapper class. // source = new Wrapper { Model = parameterized(a-edm-model) } // Always parameterize as EntityFramework does not let you inject non primitive constant values (like IEdmModel). wrapperProperty = this.ResultClrType.GetProperty("Model"); var wrapperPropertyValueExpression = LinqParameterContainer.Parameterize(typeof(IEdmModel), _model); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, wrapperPropertyValueExpression)); // Set new compute properties wrapperProperty = ResultClrType.GetProperty("Container"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, AggregationPropertyContainer.CreateNextNamedPropertyContainer(properties))); var initilizedMember = Expression.MemberInit(Expression.New(ResultClrType), wrapperTypeMemberAssignments); var selectLambda = Expression.Lambda(initilizedMember, this.LambdaParameter); var result = ExpressionHelpers.Select(query, selectLambda, this.ElementType); return(result); }
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); }
// Extract the constant that would have been encapsulated into LinqParameterContainer if this // expression represents it else return null. internal static object ExtractParameterizedConstant(Expression expression) { if (expression.NodeType == ExpressionType.MemberAccess) { MemberExpression memberAccess = expression as MemberExpression; Contract.Assert(memberAccess != null); if (memberAccess.Expression.NodeType == ExpressionType.Constant) { ConstantExpression constant = memberAccess.Expression as ConstantExpression; Contract.Assert(constant != null); Contract.Assert(constant.Value != null); LinqParameterContainer value = constant.Value as LinqParameterContainer; Contract.Assert(value != null, "Constants are already embedded into LinqParameterContainer"); return(value.Property); } } return(null); }