/// <summary> /// Executes the actual query. Called automatically when the query is evaluated /// </summary> public TResult Execute <TResult>(Expression expression) { LogLine("\r\n----------------- EXPRESSION --------------------\r\n"); var localExpression = expression; LogLine(expression.ToString()); // Reduce any parts of the expression that can be evaluated locally var simplifiedExpression = ExpressionSimplifier.Simplify(this.Queryable, localExpression); if (simplifiedExpression != localExpression) { LogLine("\r\n----------------- SIMPLIFIED EXPRESSION --------------------\r\n"); localExpression = simplifiedExpression; LogLine(localExpression.ToString()); } var pipeline = new MongoPipeline <TDocument>(_collection, AllowMongoDiskUse, LoggingDelegate); try { return(pipeline.Execute <TResult>(localExpression)); } catch (MongoCommandException c) { if (c.Message.Contains("$in requires an array as a second argument, found: null")) { throw new ArgumentNullException(".Contains on null Enumerable blew up.", c); } throw; } }
/// <summary> /// Simplify an expression by evaluating immediately any sub-trees /// that exist entirely locally. For now, that means anything that's /// not referenced from a Lambda parameter. If nothing can be evaulated /// locally, then the original expression is returned. Otherwise, a new /// expression is returned. /// </summary> /// <param name="rootQueryable">Queryable this expression is being executed against</param> /// <param name="expression">Expression to simplify</param> public static Expression Simplify(object rootQueryable, Expression expression) { // Simplification is accomplished in two passes. // Pass one, find ALL nodes that can be evaluated locally. var simplifier = new ExpressionSimplifier(); simplifier.SaveIfSimplifiable(rootQueryable, expression); // Pass two, do a depth first search of the tree greedily evaluating // nodes whenever possible. return(simplifier.Visit(expression)); }