public IQueryCommand Translate(Expression expression) { expression = Evaluator.PartialEval(expression); _sb = new StringBuilder(); _sbCustomFilter = new StringBuilder(); _expressionStack = new Stack <ExpressionType>(); Visit(expression); if (_commandOptions == null) { if (IsDynamic) { _commandOptions = new DynamicQueryCommandOptions(); } else { _commandOptions = new StandardQueryCommandOptions(_mapping, _mapping.Properties); } } if ((_falseEncountered && _sb.Length == 0) == false) { string filter; if (_pagingFilter == null) { string ocFilter = GetOcFilter(); if (_sb.Length == 0) { filter = ocFilter; } else { if (!string.IsNullOrEmpty(ocFilter)) { filter = $"(&{ocFilter}{_sb})"; } else { filter = _exclusiveWhereCount > 1 ? $"(&{_sb})" : $"{_sb}"; } } if (_customFiltersCount > 0) { var customFilter = _customFiltersCount > 1 ? $"(&{_sbCustomFilter})" : _sbCustomFilter.ToString(); filter = filter.IsNullOrEmpty() ? customFilter : $"(&{customFilter}{filter})"; } } else { filter = _pagingFilter; } _commandOptions.Filter = filter; } else { _commandOptions.YieldNoResults = true; } if ((_pagingOptions != null || (_controls?.Find(x => x is PageResultRequestControl) != null)) && _skipSize.HasValue) { throw new InvalidOperationException("Skip relies on Virtual List Views and cannot be used with simple LDAP paging. Please use one method for paging."); } _commandOptions.WithoutPaging = _withoutPaging; _commandOptions.PagingOptions = _pagingOptions; _commandOptions.SortingOptions = _sortingOptions; _commandOptions.PageSize = _toListPageSize; _commandOptions.TakeSize = _takeSize; _commandOptions.SkipSize = _skipSize; _commandOptions.Controls = _controls; _commandOptions.IsLongCount = _isLongCount; var queryCommand = QueryCommandFactory.GetCommand(_commandType, _commandOptions, _mapping); return(queryCommand); }
private void VisitQueryableMethods(MethodCallExpression m) { switch (m.Method.Name) { case "Where": _exclusiveWhereCount++; foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.StandardCommand; break; case "WithoutPaging": foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.StandardCommand; _withoutPaging = true; break; case "GetRequest": foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.GetRequestCommand; break; case "Any": if (m.Arguments.Count > 1) { _exclusiveWhereCount++; } foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.AnyCommand; break; case "FirstOrDefault": case "First": if (m.Arguments.Count > 1) { _exclusiveWhereCount++; } foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.FirstOrDefaultCommand; break; case "SingleOrDefault": if (m.Arguments.Count > 1) { _exclusiveWhereCount++; } foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.SingleOrDefaultCommand; break; case "Single": if (m.Arguments.Count > 1) { _exclusiveWhereCount++; } foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.SingleCommand; break; case "LongCount": case "Count": _isLongCount = m.Method.Name == "LongCount"; if (m.Arguments.Count > 1) { _exclusiveWhereCount++; } foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.CountCommand; break; case "ListAttributes": Dictionary <string, string> attributes = null; foreach (Expression t in m.Arguments) { if (t.Type == typeof(string[])) { attributes = (((ConstantExpression)t).Value as string[]).ToDictionary(s => s); } else { Visit(t); } } _commandOptions = new ListAttributesQueryCommandOptions(attributes); _commandType = QueryCommandType.StandardCommand; break; case "FilterWith": foreach (Expression t in m.Arguments) { if (t.Type == typeof(string)) { _sbCustomFilter.Append(((ConstantExpression)t).Value.ToString()); _customFiltersCount++; } else { Visit(t); } } _commandType = QueryCommandType.StandardCommand; break; case "Select": foreach (Expression t in m.Arguments) { var lambda = StripQuotes(t) as LambdaExpression; if (lambda != null) { if (_commandOptions != null) { throw new FilterException("Cannot have multiple Select projections."); } if (IsDynamic) { var projection = new DynamicSelectProjector(_mapping.Properties) .ProjectProperties(lambda); _commandOptions = new DynamicQueryCommandOptions(projection); } else { var projection = new SelectProjector(_mapping.Properties) .ProjectProperties(lambda); _commandOptions = new ProjectionQueryCommandOptions(_mapping, projection); } } else if (t.Type == typeof(string[])) { if (!IsDynamic) { throw new FilterException( "Cannot use a string attribute projection with a static type."); } if (_commandOptions != null) { throw new FilterException("Cannot have multiple Select projections."); } _commandOptions = new DynamicQueryCommandOptions(((ConstantExpression)t).Value as string[]); } else { Visit(t); } } _commandType = QueryCommandType.StandardCommand; break; case "ToPage": int pageSize = 0; byte[] nextPage = null; foreach (Expression t in m.Arguments) { if (t.Type == typeof(int)) { pageSize = (int)((ConstantExpression)t).Value; } else if (t.Type == typeof(byte[])) { nextPage = (byte[])((ConstantExpression)t).Value; } else if (t.Type == typeof(string)) { _pagingFilter = (string)((ConstantExpression)t).Value; } else { Visit(t); } } _pagingOptions = new PagingOptions(pageSize, nextPage); break; case "InPagesOf": foreach (Expression t in m.Arguments) { if (t.Type == typeof(int)) { _toListPageSize = (int)((ConstantExpression)t).Value; } else { Visit(t); } } _commandType = QueryCommandType.StandardCommand; break; case "ToList": foreach (Expression t in m.Arguments) { Visit(t); } _commandType = QueryCommandType.StandardCommand; break; case "Take": int takeAmount = 0; foreach (Expression t in m.Arguments) { if (t.Type == typeof(int)) { takeAmount = (int)((ConstantExpression)t).Value; } else { Visit(t); } } _takeSize = takeAmount; break; case "Skip": int skipAmount = 0; foreach (Expression t in m.Arguments) { if (t.Type == typeof(int)) { skipAmount = (int)((ConstantExpression)t).Value; } else { Visit(t); } } if (skipAmount < 0) { throw new ArgumentException("Skip value must be greater than zero."); } _skipSize = skipAmount; break; case "WithControls": if (_controls == null) { _controls = new List <DirectoryControl>(); } foreach (Expression t in m.Arguments) { IEnumerable <DirectoryControl> controls; if (t is ConstantExpression && (controls = ((ConstantExpression)t).Value as IEnumerable <DirectoryControl>) != null) { _controls.AddRange(controls); } else { Visit(t); } } break; case "OrderByDescending": case "ThenByDescending": string descRule = null; if (_sortingOptions == null) { _sortingOptions = new SortingOptions(); } foreach (Expression t in m.Arguments) { var lambda = StripQuotes(t) as LambdaExpression; if (lambda != null) { var attribute = GetMemberName((MemberExpression)lambda.Body); _sortingOptions.AddSort(attribute, true); } else if (t.Type == typeof(string)) { if (m.Arguments.IndexOf(t) == 1) { _sortingOptions.AddSort(((ConstantExpression)t).Value.ToString(), true); } else { descRule = ((ConstantExpression)t).Value.ToString(); } } else { Visit(t); } } _sortingOptions.SetMatchingRule(descRule); break; case "OrderBy": case "ThenBy": if (_sortingOptions == null) { _sortingOptions = new SortingOptions(); } string ascRule = null; foreach (Expression t in m.Arguments) { var lambda = StripQuotes(t) as LambdaExpression; if (lambda != null) { var attribute = GetMemberName((MemberExpression)lambda.Body); _sortingOptions.AddSort(attribute, false); } else if (t.Type == typeof(string)) { if (m.Arguments.IndexOf(t) == 1) { _sortingOptions.AddSort(((ConstantExpression)t).Value.ToString(), false); } else { ascRule = ((ConstantExpression)t).Value.ToString(); } } else { Visit(t); } } _sortingOptions.SetMatchingRule(ascRule); break; case "IgnoreOC": foreach (Expression t in m.Arguments) { if (t.Type == typeof(OC)) { _ignoreOc = (OC)((ConstantExpression)t).Value; } else { Visit(t); } } break; case "IncludeOC": foreach (Expression t in m.Arguments) { if (t.Type == typeof(OC)) { _includeOc = (OC)((ConstantExpression)t).Value; } else { Visit(t); } } break; } }