protected override Expression VisitSelect(DbSelectExpression select) { select = (DbSelectExpression)base.VisitSelect(select); if (select.Skip != null) { DbSelectExpression newSelect = select.SetSkip(null).SetTake(null); bool canAddColumn = !select.IsDistinct && (select.GroupBy == null || select.GroupBy.Count == 0); if (!canAddColumn) { newSelect = newSelect.AddRedundantSelect(new DbTableAlias()); } newSelect = newSelect.AddColumn(new DbColumnDeclaration("rownum", new DbRowNumberExpression(select.OrderBy))); // add layer for WHERE clause that references new rownum column newSelect = newSelect.AddRedundantSelect(new DbTableAlias()); newSelect = newSelect.RemoveColumn(newSelect.Columns.Single(c => c.Name == "rownum")); var newAlias = ((DbSelectExpression)newSelect.From).Alias; DbColumnExpression rnCol = new DbColumnExpression(typeof(int), null, newAlias, "rownum"); Expression where; if (select.Take != null) { where = new DbBetweenExpression(rnCol, Expression.Add(select.Skip, Expression.Constant(1)), Expression.Add(select.Skip, select.Take)); } else { where = rnCol.GreaterThan(select.Skip); } if (newSelect.Where != null) { where = newSelect.Where.And(where); } newSelect = newSelect.SetWhere(where); select = newSelect; } return(select); }
private Expression BindAnyAll(Expression source, MethodInfo method, LambdaExpression predicate, bool isRoot) { bool isAll = method.Name == "All"; ConstantExpression constSource = source as ConstantExpression; if (constSource != null && !IsQuery(constSource)) { System.Diagnostics.Debug.Assert(!isRoot); Expression where = null; foreach (object value in (IEnumerable)constSource.Value) { Expression expr = Expression.Invoke(predicate, Expression.Constant(value, predicate.Parameters[0].Type)); if (where == null) { where = expr; } else if (isAll) { where = where.And(expr); } else { where = where.Or(expr); } } return(this.Visit(where)); } else { if (isAll) { predicate = Expression.Lambda(Expression.Not(predicate.Body), predicate.Parameters.ToArray()); } if (predicate != null) { source = Expression.Call(typeof(Queryable), "Where", method.GetGenericArguments(), source, predicate); } DbProjectionExpression projection = this.VisitSequence(source); Expression result = new DbExistsExpression(projection.Select); if (isAll) { result = Expression.Not(result); } if (isRoot) { if (this.mapping.Language.AllowSubqueryInSelectWithoutFrom) { return(GetSingletonSequence(result, "SingleOrDefault")); } else { // use count aggregate instead of exists var newSelect = projection.Select.SetColumns( new[] { new DbColumnDeclaration("value", new DbAggregateExpression(typeof(int), DbAggregateType.Count, null, false)) } ); var colx = new DbColumnExpression(typeof(int), null, newSelect.Alias, "value"); var exp = isAll ? colx.Equal(Expression.Constant(0)) : colx.GreaterThan(Expression.Constant(0)); return(new DbProjectionExpression( newSelect, exp, Aggregator.Aggregate(typeof(bool), typeof(IEnumerable <bool>)) )); } } return(result); } }