private LambdaExpression Parameterize(Expression query, out object[] arguments) { IQueryProvider provider = this.FindProvider(query); if (provider == null) { throw new ArgumentException("Cannot deduce query provider from query"); } var ep = provider as IEntityProvider; Func <Expression, bool> fn = ep != null ? (Func <Expression, bool>)ep.CanBeEvaluatedLocally : null; List <ParameterExpression> parameters = new List <ParameterExpression>(); List <object> values = new List <object>(); var body = PartialEvaluator.Eval(query, fn, c => { bool isQueryRoot = c.Value is IQueryable; if (!isQueryRoot && ep != null && !ep.CanBeParameter(c)) { return(c); } var p = Expression.Parameter(c.Type, "p" + parameters.Count); parameters.Add(p); values.Add(c.Value); // if query root then parameterize but don't replace in the tree if (isQueryRoot) { return(c); } return(p); }); if (body.Type != typeof(object)) { body = Expression.Convert(body, typeof(object)); } arguments = values.ToArray(); if (arguments.Length < 5) { return(Expression.Lambda(body, parameters.ToArray())); } else { arguments = new object[] { arguments }; return(ExplicitToObjectArray.Rewrite(body, parameters)); } }
public virtual Expression Translate(Expression expression) { // pre-evaluate local sub-trees expression = PartialEvaluator.Eval(expression, this.mapper.Mapping.CanBeEvaluatedLocally); // apply mapping (binds LINQ operators too) expression = this.mapper.Translate(expression); // any policy specific translations or validations expression = this.police.Translate(expression); // any language specific translations or validations expression = this.linguist.Translate(expression); return(expression); }
protected override Expression VisitSelect(SelectExpression select) { // select * from table order by x skip s take t // => // select * from (select top s * from (select top s + t from table order by x) order by -x) order by x select = (SelectExpression)base.VisitSelect(select); if (select.Skip != null && select.Take != null && select.OrderBy.Count > 0) { var skip = select.Skip; var take = select.Take; var skipPlusTake = PartialEvaluator.Eval(Expression.Add(skip, take)); select = select.SetTake(skipPlusTake).SetSkip(null); select = select.AddRedundantSelect(this.language, new TableAlias()); select = select.SetTake(take); // propogate order-bys to new layer select = (SelectExpression)OrderByRewriter.Rewrite(this.language, select); var inverted = select.OrderBy.Select(ob => new OrderExpression( ob.OrderType == OrderType.Ascending ? OrderType.Descending : OrderType.Ascending, ob.Expression )); select = select.SetOrderBy(inverted); select = select.AddRedundantSelect(this.language, new TableAlias()); select = select.SetTake(Expression.Constant(0)); // temporary select = (SelectExpression)OrderByRewriter.Rewrite(this.language, select); var reverted = select.OrderBy.Select(ob => new OrderExpression( ob.OrderType == OrderType.Ascending ? OrderType.Descending : OrderType.Ascending, ob.Expression )); select = select.SetOrderBy(reverted); select = select.SetTake(null); } return(select); }
public override Expression ApplyPolicy(Expression expression, MemberInfo member) { List <LambdaExpression> ops; if (this.policy.operations.TryGetValue(member, out ops)) { var result = expression; foreach (var fnOp in ops) { var pop = PartialEvaluator.Eval(fnOp, this.Translator.Mapper.Mapping.CanBeEvaluatedLocally); result = this.Translator.Mapper.ApplyMapping(Expression.Invoke(pop, result)); } var projection = (ProjectionExpression)result; if (projection.Type != expression.Type) { var fnAgg = Aggregator.GetAggregator(expression.Type, projection.Type); projection = new ProjectionExpression(projection.Select, projection.Projector, fnAgg); } return(projection); } return(expression); }
internal IQueryProvider FindProvider(Expression expression, object[] args) { Expression root = this.FindProviderInExpression(expression) as ConstantExpression; if (root == null && args != null && args.Length > 0) { Expression replaced = ExpressionReplacer.ReplaceAll( expression, this.query.Parameters.ToArray(), args.Select((a, i) => Expression.Constant(a, this.query.Parameters[i].Type)).ToArray() ); root = this.FindProviderInExpression(replaced); } if (root != null) { ConstantExpression cex = root as ConstantExpression; if (cex == null) { cex = PartialEvaluator.Eval(root) as ConstantExpression; } if (cex != null) { IQueryProvider provider = cex.Value as IQueryProvider; if (provider == null) { IQueryable query = cex.Value as IQueryable; if (query != null) { provider = query.Provider; } } return(provider); } } return(null); }