// private static IQueryable<T> TryApplyFilter<T>(this IQueryable<T> source, VueDataTablesQuery query) // { // if (query.Filters != null && query.Filters.Any()) // { // try // { // //Only retrieve properties listed on query // var properties = typeof(T) // .GetProperties() // .Where(x => query.Filters.Any(p => p.Field.Equals(x.Name, StringComparison.OrdinalIgnoreCase))); // query.Filters.ForEach(filter => // { // var property = properties.SingleOrDefault(x => x.Name.Equals(filter.Field, StringComparison.OrdinalIgnoreCase)); // if (property != null) // source = source.BuildWhereAndQuery(property, filter.Value); // }); // } // catch // { // } // } // return source; // } private static IQueryable <T> TryApplySearch <T>(this IQueryable <T> source, VueDataTablesQuery query) { if (query?.Headers?.Where(x => !string.IsNullOrEmpty(x.Value) && !string.IsNullOrEmpty(x.Filter)).Any() == true) { var columns = new List <Header>(); //Just add valid columns with filter columns.AddRange( query.Headers .Where(x => x.Value != null && !string.IsNullOrEmpty(x.Value) && !string.IsNullOrEmpty(x.Filter)) ); //Get only referenced columns and not generic var properties = typeof(T) .GetProperties() .Where(x => !x.PropertyType.IsGenericType) .Where(x => columns.Any(c => c.Value.Equals(x.Name, StringComparison.OrdinalIgnoreCase))) .ToList(); columns.ForEach(column => { try { List <Expression> predicates = new List <Expression>(); ParameterExpression parameter = Expression.Parameter(typeof(T), Constants.X); properties.ForEach(property => { if (!column.Value.Equals(property.Name, StringComparison.OrdinalIgnoreCase)) { return; } Expression selector = Expression.PropertyOrField(parameter, property.Name); Expression predicate = selector.BuildPredicate(property, column.Filter); if (predicate != null) { predicates.Add(predicate); } }); source = source.BuildWhereOrQuery(predicates, parameter); } catch (Exception ex) { Debug.WriteLine(ex.Message); } }); } return(source); }
private static IQueryable <T> TryApplyOrder <T>(this IQueryable <T> source, VueDataTablesQuery query) { int count = 0; if (query?.SortBy?.Where(x => !string.IsNullOrEmpty(x)).Any() == true) { try { var properties = typeof(T).GetProperties(); Expression expression = source.Expression; query.SortBy.ToList().ForEach(column => { if (properties.Any(x => x.Name.Equals(column, StringComparison.OrdinalIgnoreCase))) { var parameter = Expression.Parameter(typeof(T), Constants.X); var selector = Expression.PropertyOrField(parameter, column); var method = (query.SortDesc?.FirstOrDefault() ?? false) ? (count == 0 ? Constants.OrderByDescending : Constants.ThenByDescending) : (count == 0 ? Constants.OrderBy : Constants.ThenBy); expression = Expression.Call(typeof(Queryable), method, new Type[] { source.ElementType, selector.Type }, expression, Expression.Quote(Expression.Lambda(selector, parameter))); } count++; }); if (count > 0) { source = source.Provider.CreateQuery <T>(expression); } } catch (Exception ex) { Debug.WriteLine(ex.Message); } } return(source); }
/// <summary> /// Aplica o filtro do DataTables na consulta. /// </summary> /// <typeparam name="TQueryDataType">Tipo do objeto que será retornado no DataTablesResponse, oriundo da query</typeparam> /// <typeparam name="TResponse">Tipo de response que será enviado, contendo o <paramref name="TQueryDataType"/>. Esse objeto precisa herdar de <seealso cref="DataTablesResponse<>" /></typeparam> /// <param name="source">Query não materializada que será utilizada para aplicação do filtro e ordenação</param> /// <param name="query">Objeto query do datatables, contendo os filtros e a ordenação</param> /// <returns>Esse método irá materializar a query, aplicando os filtros e a ordenação do DataTables</returns> public static TResponse FilterDataTable <TQueryDataType, TResponse>(this IQueryable <TQueryDataType> source, VueDataTablesQuery query) where TResponse : DataTablesResponse <TQueryDataType>, new() { var originalSource = source; var totalRecords = source.Count(); var recordsFiltered = totalRecords; if (query == null) { source = source.Take(10); } if (query != null) { //TODO: implement a column filter //source = source.TryApplyFilter(query); source = source.TryApplySearch(query); if (originalSource != source) //Prevent a double count for same result { recordsFiltered = source.Count(); totalRecords = recordsFiltered; //On VueDT, the total should reflect the filtered count } if (query.ItemsPerPage >= 0) { source = source.Skip((query.Page - 1) * query.ItemsPerPage).Take(query.ItemsPerPage); } source = source.TryApplyOrder(query); } return(new TResponse() { RecordsTotal = totalRecords, RecordsFiltered = recordsFiltered, Data = source.ToList() }); }
/// <summary> /// Aplica o filtro do DataTables na consulta. /// </summary> /// <typeparam name="TQueryDataType">Tipo do objeto que será retornado no DataTablesResponse, oriundo da query</typeparam> /// <typeparam name="TResponse">Tipo de response que será enviado, contendo o <paramref name="TQueryDataType"/>. Esse objeto precisa herdar de <seealso cref="DataTablesResponse<>" /></typeparam> /// <param name="source">Query não materializada que será utilizada para aplicação do filtro e ordenação</param> /// <param name="query">Objeto query do datatables, contendo os filtros e a ordenação</param> /// <returns>Esse método irá materializar a query, aplicando os filtros e a ordenação do DataTables</returns> public static Task <TResponse> FilterDataTableAsync <TQueryDataType, TResponse>(this IQueryable <TQueryDataType> source, VueDataTablesQuery query, CancellationToken cancellationToken) where TResponse : DataTablesResponse <TQueryDataType>, new() { return(Task.Run(() => FilterDataTable <TQueryDataType, TResponse>(source, query), cancellationToken)); }