// private methods private void CombinePredicateWithWhereClause(MethodCallExpression methodCallExpression, LambdaExpression predicate) { if (predicate != null) { if (_projection != null) { var message = string.Format("{0} with predicate after a projection is not supported.", methodCallExpression.Method.Name); throw new NotSupportedException(message); } if (_where == null) { _where = predicate; return; } if (_where.Parameters.Count != 1) { throw new MongoInternalException("Where lambda expression should have one parameter."); } var whereBody = _where.Body; var whereParameter = _where.Parameters[0]; if (predicate.Parameters.Count != 1) { throw new MongoInternalException("Predicate lambda expression should have one parameter."); } var predicateBody = predicate.Body; var predicateParameter = predicate.Parameters[0]; // when using OfType the parameter types might not match (but they do have to be compatible) ParameterExpression parameter; if (predicateParameter.Type.IsAssignableFrom(whereParameter.Type)) { predicateBody = ExpressionParameterReplacer.ReplaceParameter(predicateBody, predicateParameter, whereParameter); parameter = whereParameter; } else if (whereParameter.Type.IsAssignableFrom(predicateParameter.Type)) { whereBody = ExpressionParameterReplacer.ReplaceParameter(whereBody, whereParameter, predicateParameter); parameter = predicateParameter; } else { throw new NotSupportedException("Can't combine existing where clause with new predicate because parameter types are incompatible."); } var combinedBody = Expression.AndAlso(whereBody, predicateBody); _where = Expression.Lambda(combinedBody, parameter); } }
/// <summary> /// Executes the translated Find query. /// </summary> /// <returns>The result of executing the translated Find query.</returns> public override object Execute() { var query = BuildQuery(); if (_distinct) { return(ExecuteDistinct(query)); } var cursor = Collection.FindAs(DocumentType, query); if (_orderBy != null) { var sortBy = new SortByDocument(); foreach (var clause in _orderBy) { var keyExpression = clause.Key.Body; var serializationInfo = _serializationInfoHelper.GetSerializationInfo(keyExpression); var direction = (clause.Direction == OrderByDirection.Descending) ? -1 : 1; sortBy.Add(serializationInfo.ElementName, direction); } cursor.SetSortOrder(sortBy); } if (_skip != null) { cursor.SetSkip(ToInt32(_skip)); } if (_take != null) { cursor.SetLimit(ToInt32(_take)); } var projection = _projection; if (_ofType != null) { if (projection == null) { var paramExpression = Expression.Parameter(DocumentType, "x"); var convertExpression = Expression.Convert(paramExpression, _ofType); projection = Expression.Lambda(convertExpression, paramExpression); } else { var paramExpression = Expression.Parameter(DocumentType, "x"); var convertExpression = Expression.Convert(paramExpression, _ofType); var body = ExpressionParameterReplacer.ReplaceParameter(projection.Body, projection.Parameters[0], convertExpression); projection = Expression.Lambda(body, paramExpression); } } IEnumerable enumerable; if (projection == null) { enumerable = cursor; } else { var lambdaType = projection.GetType(); var delegateType = lambdaType.GetGenericArguments()[0]; var sourceType = delegateType.GetGenericArguments()[0]; var resultType = delegateType.GetGenericArguments()[1]; var projectorType = typeof(Projector <,>).MakeGenericType(sourceType, resultType); var compiledProjection = projection.Compile(); var projector = Activator.CreateInstance(projectorType, cursor, compiledProjection); enumerable = (IEnumerable)projector; } if (_elementSelector != null) { return(_elementSelector(enumerable)); } else { return(enumerable); } }
// public methods /// <summary> /// Replaces all occurences of one parameter with a different parameter. /// </summary> /// <param name="node">The expression containing the parameter that should be replaced.</param> /// <param name="fromParameter">The from parameter.</param> /// <param name="toExpression">The expression that replaces the parameter.</param> /// <returns>The expression with all occurrences of the parameter replaced.</returns> public static Expression ReplaceParameter(Expression node, ParameterExpression fromParameter, Expression toExpression) { var replacer = new ExpressionParameterReplacer(fromParameter, toExpression); return(replacer.Visit(node)); }
/// <summary> /// Executes the translated Find query. /// </summary> /// <returns>The result of executing the translated Find query.</returns> public override object Execute() { if (_take.HasValue && _take.Value == 0) { var type = _ofType ?? DocumentType; return(typeof(Enumerable).GetMethod("Empty").MakeGenericMethod(type).Invoke(null, null)); } var query = BuildQuery(); if (_distinct != null) { return(ExecuteDistinct(query)); } var cursor = Collection.FindAs(DocumentType, query); if (_orderBy != null) { var sortBy = new SortByDocument(); foreach (var clause in _orderBy) { var keyExpression = clause.Key.Body; var serializationInfo = _serializationInfoHelper.GetSerializationInfo(keyExpression); var direction = (clause.Direction == OrderByDirection.Descending) ? -1 : 1; sortBy.Add(serializationInfo.ElementName, direction); } cursor.SetSortOrder(sortBy); } if (_skip != null) { cursor.SetSkip(_skip.Value); } if (_take != null) { cursor.SetLimit(_take.Value); } if (_indexHint != null) { if (_indexHint.IsString) { cursor.SetHint(_indexHint.AsString); } else if (_indexHint.IsBsonDocument) { cursor.SetHint(_indexHint.AsBsonDocument); } else { throw new NotSupportedException("Index hints must be strings or documents"); } } var projection = _projection; if (_ofType != null) { if (projection == null) { var paramExpression = Expression.Parameter(DocumentType, "x"); var convertExpression = Expression.Convert(paramExpression, _ofType); projection = Expression.Lambda(convertExpression, paramExpression); } else { var paramExpression = Expression.Parameter(DocumentType, "x"); var convertExpression = Expression.Convert(paramExpression, _ofType); var body = ExpressionParameterReplacer.ReplaceParameter(projection.Body, projection.Parameters[0], convertExpression); projection = Expression.Lambda(body, paramExpression); } } IProjector projector; if (projection == null) { var projectorType = typeof(IdentityProjector <>).MakeGenericType(DocumentType); projector = (IProjector)Activator.CreateInstance(projectorType, cursor); } else { var lambdaType = projection.GetType(); var delegateType = lambdaType.GetGenericArguments()[0]; var sourceType = delegateType.GetGenericArguments()[0]; var resultType = delegateType.GetGenericArguments()[1]; var projectorType = typeof(Projector <,>).MakeGenericType(sourceType, resultType); var compiledProjection = projection.Compile(); projector = (IProjector)Activator.CreateInstance(projectorType, cursor, compiledProjection); } if (_elementSelector != null) { return(_elementSelector(projector)); } else { return(projector); } }
// public methods /// <summary> /// Replaces all occurences of one parameter with a different parameter. /// </summary> /// <param name="node">The expression containing the parameter that should be replaced.</param> /// <param name="fromParameter">The from parameter.</param> /// <param name="toExpression">The expression that replaces the parameter.</param> /// <returns>The expression with all occurrences of the parameter replaced.</returns> public static Expression ReplaceParameter(Expression node, ParameterExpression fromParameter, Expression toExpression) { var replacer = new ExpressionParameterReplacer(fromParameter, toExpression); return replacer.Visit(node); }