예제 #1
0
        // 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 SequoiaInternalException("Where lambda expression should have one parameter.");
                }
                var whereBody      = _where.Body;
                var whereParameter = _where.Parameters[0];

                if (predicate.Parameters.Count != 1)
                {
                    throw new SequoiaInternalException("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);
            }
        }
        // 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));
        }
 // 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);
 }
예제 #4
0
        /// <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);

            DBQuery dbQuery = new DBQuery();

            dbQuery.Matcher = query as BsonDocument;

            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);
                dbQuery.OrderBy = sortBy;
            }

            if (_skip != null)
            {
                //cursor.SetSkip(_skip.Value);
                dbQuery.SkipRowsCount = _skip.Value;
            }

            if (_take != null)
            {
                //cursor.SetLimit(_take.Value);
                dbQuery.ReturnRowsCount = _take.Value;
            }

            if (_indexHint != null)
            {
                if (_indexHint.IsString)
                {
                    //cursor.SetHint(_indexHint.AsString);
                }
                else if (_indexHint.IsBsonDocument)
                {
                    //cursor.SetHint(_indexHint.AsBsonDocument);
                    dbQuery.Hint = _indexHint.AsBsonDocument;
                }
                else
                {
                    throw new NotSupportedException("Index hints must be strings or documents");
                }
            }

            var cursor = Collection.Query(dbQuery);

            cursor.DBQuery = dbQuery;

            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);
            }
        }