// 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 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 }); return(query.Provider.CreateQuery(skipQuery)); }
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 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); }
// Generates the expression // source => new Wrapper { Instance = source, Container = new PropertyContainer { ..expanded properties.. } } private Expression ProjectElement(Expression source, SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource) { Contract.Assert(source != null); Type elementType = source.Type; Type wrapperType = typeof(SelectExpandWrapper <>).MakeGenericType(elementType); List <MemberAssignment> wrapperTypeMemberAssignments = new List <MemberAssignment>(); PropertyInfo wrapperProperty; Expression wrapperPropertyValueExpression; bool isInstancePropertySet = false; bool isTypeNamePropertySet = false; bool isContainerPropertySet = false; // Initialize property 'ModelID' on the wrapper class. // source = new Wrapper { ModelID = 'some-guid-id' } wrapperProperty = wrapperType.GetProperty("ModelID"); wrapperPropertyValueExpression = _settings.EnableConstantParameterization ? LinqParameterContainer.Parameterize(typeof(string), _modelID) : Expression.Constant(_modelID); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, wrapperPropertyValueExpression)); if (IsSelectAll(selectExpandClause)) { // Initialize property 'Instance' on the wrapper class wrapperProperty = wrapperType.GetProperty("Instance"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, source)); wrapperProperty = wrapperType.GetProperty("UseInstanceForProperties"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, Expression.Constant(true))); isInstancePropertySet = true; } else { // Initialize property 'TypeName' on the wrapper class as we don't have the instance. Expression typeName = CreateTypeNameExpression(source, structuredType, _model); if (typeName != null) { isTypeNamePropertySet = true; wrapperProperty = wrapperType.GetProperty("InstanceType"); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, typeName)); } } // Initialize the property 'Container' on the wrapper class // source => new Wrapper { Container = new PropertyContainer { .... } } if (selectExpandClause != null) { Dictionary <IEdmNavigationProperty, ExpandedReferenceSelectItem> propertiesToExpand = GetPropertiesToExpandInQuery(selectExpandClause); ISet <IEdmStructuralProperty> autoSelectedProperties; ISet <IEdmStructuralProperty> propertiesToInclude = GetPropertiesToIncludeInQuery(selectExpandClause, structuredType, navigationSource, _model, out autoSelectedProperties); bool isSelectingOpenTypeSegments = GetSelectsOpenTypeSegments(selectExpandClause, structuredType); if (propertiesToExpand.Count > 0 || propertiesToInclude.Count > 0 || autoSelectedProperties.Count > 0 || isSelectingOpenTypeSegments) { Expression propertyContainerCreation = BuildPropertyContainer(structuredType, source, propertiesToExpand, propertiesToInclude, autoSelectedProperties, isSelectingOpenTypeSegments); if (propertyContainerCreation != null) { wrapperProperty = wrapperType.GetProperty("Container"); Contract.Assert(wrapperProperty != null); wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, propertyContainerCreation)); isContainerPropertySet = true; } } } Type wrapperGenericType = GetWrapperGenericType(isInstancePropertySet, isTypeNamePropertySet, isContainerPropertySet); wrapperType = wrapperGenericType.MakeGenericType(elementType); return(Expression.MemberInit(Expression.New(wrapperType), wrapperTypeMemberAssignments)); }