protected virtual Expression VisitProjection(ProjectionExpression projection) { var source = (SelectExpression)Visit(projection.Source); var projector = Visit(projection.Projector); if (source != projection.Source || projector != projection.Projector) return new ProjectionExpression(source, projector, projection.Aggregator); return projection; }
protected override Expression VisitProjection(ProjectionExpression projection) { var queryObject = new MongoQueryObjectBuilder().Build(projection); queryObject.Projector = new ProjectionBuilder().Build(projection.Projector, queryObject.DocumentType, "document", queryObject.IsMapReduce); queryObject.Aggregator = (LambdaExpression)Visit(projection.Aggregator); Expression result = Expression.Call( _provider, "ExecuteQueryObject", Type.EmptyTypes, Expression.Constant(queryObject, typeof(MongoQueryObject))); if (queryObject.Aggregator != null) result = Expression.Convert(result, queryObject.Aggregator.Body.Type); else result = Expression.Convert(result, typeof(IEnumerable<>).MakeGenericType(queryObject.Projector.Body.Type)); return result; }
protected virtual Expression BindGroupBy(Expression source, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector) { var projection = VisitSequence(source); _map[keySelector.Parameters[0]] = projection.Projector; var keyExpression = Visit(keySelector.Body); var elementExpression = projection.Projector; if (elementSelector != null) { _map[elementSelector.Parameters[0]] = projection.Projector; elementExpression = Visit(elementSelector.Body); } var subqueryBasis = VisitSequence(source); _map[keySelector.Parameters[0]] = subqueryBasis.Projector; var subqueryKeyExpression = Visit(keySelector.Body); var subqueryCorrelation = Expression.Equal(keyExpression, subqueryKeyExpression); var subqueryElementExpression = subqueryBasis.Projector; if (elementSelector != null) { _map[elementSelector.Parameters[0]] = subqueryBasis.Projector; subqueryElementExpression = Visit(elementSelector.Body); } var elementAlias = new Alias(); var elementProjection = _projector.ProjectFields(subqueryElementExpression, elementAlias, subqueryBasis.Source.Alias); var elementSubquery = new ProjectionExpression( new SelectExpression(elementAlias, elementProjection.Fields, subqueryBasis.Source, subqueryCorrelation), elementProjection.Projector); var alias = new Alias(); var info = new GroupByInfo(alias, elementExpression); _groupByMap[elementSubquery] = info; Expression resultExpression; if (resultSelector != null) { var saveGroupElement = _currentGroupElement; _currentGroupElement = elementSubquery; _map[resultSelector.Parameters[0]] = keyExpression; _map[resultSelector.Parameters[1]] = elementSubquery; resultExpression = Visit(resultSelector.Body); _currentGroupElement = saveGroupElement; } else { resultExpression = Expression.New( typeof(Grouping<,>).MakeGenericType(keyExpression.Type, subqueryElementExpression.Type).GetConstructors()[0], new[] { keyExpression, elementSubquery }); } var fieldProjection = _projector.ProjectFields(resultExpression, alias, projection.Source.Alias); var projectedElementSubquery = ((NewExpression)fieldProjection.Projector).Arguments[1]; _groupByMap[projectedElementSubquery] = info; return new ProjectionExpression( new SelectExpression(alias, new FieldDeclaration[0], projection.Source, null, null, keyExpression, false, null, null), fieldProjection.Projector); }
private Expression BindFirstOrSingle(Expression source, LambdaExpression predicate, string kind, bool isRoot) { var projection = VisitSequence(source); Expression where = null; if (predicate != null) { _map[predicate.Parameters[0]] = projection.Projector; where = Visit(predicate.Body); } Expression take = kind.StartsWith("First") ? Expression.Constant(1) : null; if (take == null & kind.StartsWith("Single")) take = Expression.Constant(2); if (take != null || where != null) { var alias = new Alias(); var fieldProjection = _projector.ProjectFields(projection.Projector, alias, projection.Source.Alias); projection = new ProjectionExpression( new SelectExpression(alias, fieldProjection.Fields, projection.Source, where, null, null, false, null, take), fieldProjection.Projector); } if (isRoot) { var elementType = projection.Projector.Type; var p = Expression.Parameter(typeof(IEnumerable<>).MakeGenericType(elementType), "p"); var lambda = Expression.Lambda(Expression.Call(typeof(Enumerable), kind, new[] { elementType }, p), p); return new ProjectionExpression(projection.Source, projection.Projector, lambda); } return projection; }
protected virtual bool CompareProjection(ProjectionExpression a, ProjectionExpression b) { if (!Compare(a.Source, b.Source)) return false; var save = _aliasScope; try { _aliasScope = new ScopedDictionary<Alias, Alias>(_aliasScope); _aliasScope.Add(a.Source.Alias, b.Source.Alias); return Compare(a.Projector, b.Projector) && Compare(a.Aggregator, b.Aggregator) && a.IsSingleton == b.IsSingleton; } finally { _aliasScope = save; } }