using PoweredSoft.DynamicLinq.Helpers; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace PoweredSoft.DynamicLinq.Fluent { public class QueryBuilder : QueryBuilderBase { public IQueryable Query { get; set; } public Type QueryableType { get; set; } public QueryBuilder(IQueryable query) { Query = query; } public virtual IQueryable Build() { // the query. var query = Query; // build the filters. query = BuildFilters(query); // build the sorts query = BuildSorts(query); return query; } public virtual QueryBuilder OrderBy(string path) { Sorts.Clear(); Sorts.Add(new QueryBuilderSort { Path = path, SortOrder = SortOrder.Ascending, AppendSort = false }); return this; } public virtual QueryBuilder OrderByDescending(string path) { Sorts.Clear(); Sorts.Add(new QueryBuilderSort { Path = path, SortOrder = SortOrder.Descending, AppendSort = false }); return this; } public virtual QueryBuilder ThenBy(string path) { Sorts.Add(new QueryBuilderSort { Path = path, SortOrder = SortOrder.Ascending, AppendSort = true }); return this; } public virtual QueryBuilder ThenByDescending(string path) { Sorts.Add(new QueryBuilderSort { Path = path, SortOrder = SortOrder.Descending, AppendSort = true }); return this; } protected virtual IQueryable BuildSorts(IQueryable query) { Sorts.ForEach(sort => { query = QueryableHelpers.CreateSortExpression(query, sort.Path, sort.SortOrder, sort.AppendSort); }); return query; } protected virtual IQueryable BuildFilters(IQueryable query) { if (Filters == null || Filters?.Count() == 0) return query; // shared parameter. var sharedParameter = Expression.Parameter(typeof(T), "t"); // build the expression. var filterExpressionMerged = BuildFilterExpression(sharedParameter, Filters); // make changes on the query. query = query.Where(filterExpressionMerged); return query; } protected virtual Expression> BuildFilterExpression(ParameterExpression parameter, List filters) { Expression> temp = null; filters.ForEach(filter => { Expression> innerExpression; if (filter.Filters?.Any() == true) innerExpression = BuildFilterExpression(parameter, filter.Filters); else innerExpression = BuildFilterExpression(parameter, filter); if (temp == null) { temp = innerExpression; } else { if (filter.And) temp = Expression.Lambda>(Expression.AndAlso(temp.Body, innerExpression.Body), parameter); else temp = Expression.Lambda>(Expression.OrElse(temp.Body, innerExpression.Body), parameter); } }); return temp; } protected virtual Expression> BuildFilterExpression(ParameterExpression parameter, QueryBuilderFilter filter) { var ret = QueryableHelpers.CreateFilterExpression( filter.Path, filter.ConditionOperator, filter.Value, filter.ConvertStrategy, filter.CollectionHandling, parameter: parameter, nullChecking: IsNullCheckingEnabled ); return ret; } protected override QueryBuilderBase GetSubQueryBuilder() { return new QueryBuilder(Query); } } }