public static IQueryable <T> ApplyFilteringAndOrdering <T>(this IQueryable <T> query, IGridifyQuery?gridifyQuery, IGridifyMapper <T>?mapper = null) { query = query.ApplyFiltering(gridifyQuery, mapper); query = query.ApplyOrdering(gridifyQuery, mapper); return(query); }
public static bool IsValid <T>(this IGridifyFiltering filtering, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(filtering.Filter)) { return(true); } try { var parser = new Parser(filtering.Filter !, GridifyGlobalConfiguration.CustomOperators.Operators); var syntaxTree = parser.Parse(); if (syntaxTree.Diagnostics.Any()) { return(false); } var fieldExpressions = syntaxTree.Root.Descendants() .Where(q => q.Kind is SyntaxKind.FieldExpression) .Cast <FieldExpressionSyntax>().ToList(); mapper ??= new GridifyMapper <T>(true); if (fieldExpressions.Any(field => !mapper.HasMap(field.FieldToken.Text))) { return(false); } } catch (Exception) { return(false); } return(true); }
/// <summary> /// if given mapper was null this function creates default generated mapper /// </summary> /// <param name="mapper">a <c>GridifyMapper<c /> that can be null</param> /// <param name="syntaxTree">optional syntaxTree to Lazy mapping generation</param> /// <typeparam name="T">type to set mappings</typeparam> /// <returns>return back mapper or new generated mapper if it was null</returns> private static IGridifyMapper <T> FixMapper <T>(this IGridifyMapper <T>?mapper, SyntaxTree syntaxTree) { if (mapper != null) { return(mapper); } mapper = new GridifyMapper <T>(); foreach (var field in syntaxTree.Root.Descendants() .Where(q => q.Kind == SyntaxKind.FieldExpression) .Cast <FieldExpressionSyntax>()) { try { mapper.AddMap(field.FieldToken.Text); } catch (Exception) { if (!mapper.Configuration.IgnoreNotMappedFields) { throw new GridifyMapperException($"Property '{field.FieldToken.Text}' not found."); } } } return(mapper); }
public static async Task <Paging <T> > GridifyAsync <T>(this IQueryable <T> query, IGridifyQuery gridifyQuery, CancellationToken token, IGridifyMapper <T>?mapper = null) { var(count, queryable) = await query.GridifyQueryableAsync(gridifyQuery, mapper, token); return(new Paging <T>(count, await queryable.ToListAsync(token))); }
public static async Task <QueryablePaging <T> > GridifyQueryableAsync <T>(this IQueryable <T> query, IGridifyQuery gridifyQuery, IGridifyMapper <T>?mapper, CancellationToken token) { query = query.ApplyFiltering(gridifyQuery, mapper); var count = await query.CountAsync(token); query = query.ApplyOrdering(gridifyQuery, mapper); query = query.ApplyPaging(gridifyQuery); return(new QueryablePaging <T>(count, query)); }
/// <summary> /// adds Ordering to the query /// </summary> /// <param name="query">the original(target) queryable object</param> /// <param name="gridifyOrdering">the configuration to apply ordering</param> /// <param name="groupOrder">select group member for ordering</param> /// // need to be more specific /// <param name="isGroupOrderAscending"></param> /// <param name="mapper">this is an optional parameter to apply ordering using a custom mapping configuration</param> /// <typeparam name="T">type of target entity</typeparam> /// <typeparam name="TKey">type of target property</typeparam> /// <returns>returns user query after applying Ordering </returns> public static IQueryable <T> ApplyOrdering <T, TKey>(this IQueryable <T> query, IGridifyOrdering?gridifyOrdering, Expression <Func <T, TKey> > groupOrder, bool isGroupOrderAscending = true, IGridifyMapper <T>?mapper = null) { if (gridifyOrdering == null) { return(query); } if (string.IsNullOrWhiteSpace(gridifyOrdering.OrderBy)) { return(query); } query = isGroupOrderAscending ? query.OrderBy(groupOrder) : query.OrderByDescending(groupOrder); query = ProcessOrdering(query, gridifyOrdering.OrderBy !, true, mapper); return(query); }
public static bool IsValid <T>(this IGridifyOrdering ordering, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(ordering.OrderBy)) { return(true); } try { var orders = ParseOrderings(ordering.OrderBy !).ToList(); mapper ??= new GridifyMapper <T>(true); if (orders.Any(order => !mapper.HasMap(order.MemberName))) { return(false); } } catch (Exception) { return(false); } return(true); }
public static IQueryable <T> ApplyFiltering <T>(this IQueryable <T> query, IGridifyFiltering?gridifyFiltering, IGridifyMapper <T>?mapper = null) { if (gridifyFiltering == null) { return(query); } return(string.IsNullOrWhiteSpace(gridifyFiltering.Filter) ? query : ApplyFiltering(query, gridifyFiltering.Filter, mapper)); }
/// <summary> /// adds Ordering to the query /// </summary> /// <param name="query">the original(target) queryable object</param> /// <param name="orderBy">the ordering fields</param> /// <param name="mapper">this is an optional parameter to apply ordering using a custom mapping configuration</param> /// <param name="startWithThenBy"> /// if you already have an ordering with start with ThenBy, new orderings will add on top of /// your orders /// </param> /// <typeparam name="T">type of target entity</typeparam> /// <returns>returns user query after applying Ordering </returns> public static IQueryable <T> ApplyOrdering <T>(this IQueryable <T> query, string orderBy, IGridifyMapper <T>?mapper = null, bool startWithThenBy = false) { return(string.IsNullOrWhiteSpace(orderBy) ? query : ProcessOrdering(query, orderBy, startWithThenBy, mapper)); }
/// <summary> /// gets a query or collection, /// adds filtering, ordering and paging /// loads filtered and sorted data /// return pagination ready result /// </summary> /// <param name="query">the original(target) queryable object</param> /// <param name="queryOption">the configuration to apply paging, filtering and ordering</param> /// <param name="mapper">this is an optional parameter to apply filtering and ordering using a custom mapping configuration</param> /// <typeparam name="T">type of target entity</typeparam> /// <returns>returns a loaded <c>Paging<T><c /> after applying filtering, ordering and paging </returns> /// <returns></returns> public static Paging <T> Gridify <T>(this IQueryable <T> query, Action <IGridifyQuery> queryOption, IGridifyMapper <T>?mapper = null) { var gridifyQuery = new GridifyQuery(); queryOption.Invoke(gridifyQuery); var(count, queryable) = query.GridifyQueryable(gridifyQuery, mapper); return(new Paging <T>(count, queryable.ToList())); }
/// <summary> /// gets a query or collection, /// adds filtering, ordering and paging /// loads filtered and sorted data /// return pagination ready result /// </summary> /// <param name="query">the original(target) queryable object</param> /// <param name="gridifyQuery">the configuration to apply paging, filtering and ordering</param> /// <param name="mapper">this is an optional parameter to apply filtering and ordering using a custom mapping configuration</param> /// <typeparam name="T">type of target entity</typeparam> /// <returns>returns a loaded <c>Paging<T><c /> after applying filtering, ordering and paging </returns> /// <returns></returns> public static Paging <T> Gridify <T>(this IQueryable <T> query, IGridifyQuery?gridifyQuery, IGridifyMapper <T>?mapper = null) { var(count, queryable) = query.GridifyQueryable(gridifyQuery, mapper); return(new Paging <T>(count, queryable.ToList())); }
/// <summary> /// gets a query or collection, /// adds filtering, /// Get totalItems Count /// adds ordering and paging /// return QueryablePaging with TotalItems and an IQueryable Query /// </summary> /// <param name="query">the original(target) queryable object</param> /// <param name="gridifyQuery">the configuration to apply paging, filtering and ordering</param> /// <param name="mapper">this is an optional parameter to apply filtering and ordering using a custom mapping configuration</param> /// <typeparam name="T">type of target entity</typeparam> /// <returns>returns a <c>QueryablePaging<T><c/> after applying filtering, ordering and paging</returns> public static QueryablePaging <T> GridifyQueryable <T>(this IQueryable <T> query, IGridifyQuery?gridifyQuery, IGridifyMapper <T>?mapper = null) { query = query.ApplyFiltering(gridifyQuery, mapper); var count = query.Count(); query = query.ApplyOrdering(gridifyQuery, mapper); query = query.ApplyPaging(gridifyQuery); return(new QueryablePaging <T>(count, query)); }
public static Expression <Func <T, bool> > CreateQuery <T>(this SyntaxTree syntaxTree, IGridifyMapper <T>?mapper = null) { mapper = mapper.FixMapper(syntaxTree); var exp = ExpressionToQueryConvertor.GenerateQuery(syntaxTree.Root, mapper).Expression; if (exp == null) { throw new GridifyQueryException("Invalid SyntaxTree."); } return(exp); }
public static IQueryable <object> ApplySelect <T>(this IQueryable <T> query, string props, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(props)) { return((IQueryable <object>)query); } if (mapper is null) { mapper = new GridifyMapper <T>(true); } var exp = mapper.GetExpression(props); var result = query.Select(exp); return(result); }
public static IQueryable <T> ApplyFiltering <T>(this IQueryable <T> query, string?filter, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(filter)) { return(query); } var syntaxTree = SyntaxTree.Parse(filter !, GridifyGlobalConfiguration.CustomOperators.Operators); if (syntaxTree.Diagnostics.Any()) { throw new GridifyFilteringException(syntaxTree.Diagnostics.Last()); } mapper = mapper.FixMapper(syntaxTree); var(queryExpression, _) = ExpressionToQueryConvertor.GenerateQuery(syntaxTree.Root, mapper); query = query.Where(queryExpression); return(query); }
public static IEnumerable <Expression <Func <T, object> > > GetOrderingExpressions <T>(this IGridifyOrdering gridifyOrdering, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(gridifyOrdering.OrderBy)) { throw new GridifyQueryException("OrderBy is not defined or not Found"); } var members = ParseOrderings(gridifyOrdering.OrderBy !).Select(q => q.MemberName).ToList(); if (mapper is null) { foreach (var member in members) { Expression <Func <T, object> >?exp = null; try { exp = GridifyMapper <T> .CreateExpression(member); } catch (Exception) { // skip if there is no mappings available } if (exp != null) { yield return(exp); } } } else { foreach (var member in members.Where(mapper.HasMap)) { yield return(mapper.GetExpression(member) !); } } }
private static Expression <Func <T, bool> > GetExpressionFromCondition <T> (string condition, IGridifyQuery gridifyQuery, IGridifyMapper <T> mapper) { try { string[] op = { "==", "!=", "=*", "!*", ">>", "<<", ">=", "<=" }; var maps = ParseFilter(condition, op); if (!maps.HasValue) { return(null); } var gMap = mapper.GetGMap(maps.Value.Left); Expression <Func <T, object> > exp = gMap.To; var body = exp.Body; // Remove the boxing for value types if (body.NodeType == ExpressionType.Convert) { body = ((UnaryExpression)body).Operand; } object value = maps.Value.Right; // execute user custom Convertor if (gMap.Convertor != null) { value = gMap.Convertor.Invoke(maps.Value.Right); } if (value != null && body.Type != value.GetType()) { try { // handle broken guids, github issue #2 if (body.Type == typeof(Guid) && !Guid.TryParse(value.ToString(), out _)) { value = Guid.NewGuid(); } var converter = TypeDescriptor.GetConverter(body.Type); value = converter.ConvertFromString(value.ToString()); } catch (System.FormatException) { // return no records in case of any exception in formating return(q => false); } } Expression be = null; var ContainsMethod = typeof(string).GetMethod("Contains", new [] { typeof(string) }); switch (maps.Value.Operation) { case "==": be = Expression.Equal(body, Expression.Constant(value, body.Type)); break; case "!=": be = Expression.NotEqual(body, Expression.Constant(value, body.Type)); break; case ">>": be = Expression.GreaterThan(body, Expression.Constant(value, body.Type)); break; case "<<": be = Expression.LessThan(body, Expression.Constant(value, body.Type)); break; case ">=": be = Expression.GreaterThanOrEqual(body, Expression.Constant(value, body.Type)); break; case "<=": be = Expression.LessThanOrEqual(body, Expression.Constant(value, body.Type)); break; case "=*": be = Expression.Call(body, ContainsMethod, Expression.Constant(value, body.Type)); break; case "!*": be = Expression.Not(Expression.Call(body, ContainsMethod, Expression.Constant(value, body.Type))); break; default: return(null); } return(Expression.Lambda <Func <T, bool> > (be, exp.Parameters)); } catch (Exception) { return(null); } }
public async static Task <Paging <T> > GridifyAsync <T> (this IQueryable <T> query, IGridifyQuery gridifyQuery, IGridifyMapper <T> mapper = null) { mapper = mapper.FixMapper(); var res = await query.GridifyQueryableAsync(gridifyQuery, mapper); return(new Paging <T> () { Items = await res.Query.ToListAsync(), TotalItems = res.TotalItems }); }
internal static Expression <Func <T, object> > GetOrderExpression <T>(ParsedOrdering order, IGridifyMapper <T> mapper) { var exp = mapper.GetExpression(order.MemberName); switch (order.OrderingType) { case OrderingType.Normal: return(exp); case OrderingType.NullCheck: case OrderingType.NotNullCheck: default: { // member should be nullable if (exp.Body is not UnaryExpression unary || Nullable.GetUnderlyingType(unary.Operand.Type) == null) { throw new GridifyOrderingException($"'{order.MemberName}' is not nullable type"); } var prop = Expression.Property(exp.Parameters[0], order.MemberName); var hasValue = Expression.PropertyOrField(prop, "HasValue"); switch (order.OrderingType) { case OrderingType.NullCheck: { var boxedExpression = Expression.Convert(hasValue, typeof(object)); return(Expression.Lambda <Func <T, object> >(boxedExpression, exp.Parameters)); } case OrderingType.NotNullCheck: { var notHasValue = Expression.Not(hasValue); var boxedExpression = Expression.Convert(notHasValue, typeof(object)); return(Expression.Lambda <Func <T, object> >(boxedExpression, exp.Parameters)); } // should never reach here case OrderingType.Normal: return(exp); default: throw new ArgumentOutOfRangeException(); } } } }
internal static IQueryable <T> ProcessOrdering <T>(IQueryable <T> query, string orderings, bool startWithThenBy, IGridifyMapper <T>?mapper) { var isFirst = !startWithThenBy; var orders = ParseOrderings(orderings).ToList(); // build the mapper if it is null if (mapper is null) { mapper = new GridifyMapper <T>(); foreach (var order in orders) { try { mapper.AddMap(order.MemberName); } catch (Exception) { if (!mapper.Configuration.IgnoreNotMappedFields) { throw new GridifyMapperException($"Mapping '{order.MemberName}' not found"); } } } } foreach (var order in orders) { if (!mapper.HasMap(order.MemberName)) { // skip if there is no mappings available if (mapper.Configuration.IgnoreNotMappedFields) { continue; } throw new GridifyMapperException($"Mapping '{order.MemberName}' not found"); } if (isFirst) { query = query.OrderByMember(GetOrderExpression(order, mapper), order.IsAscending); isFirst = false; } else { query = query.ThenByMember(GetOrderExpression(order, mapper), order.IsAscending); } } return(query); }
public static Expression <Func <T, bool> > GetFilteringExpression <T>(this IGridifyFiltering gridifyFiltering, IGridifyMapper <T>?mapper = null) { if (string.IsNullOrWhiteSpace(gridifyFiltering.Filter)) { throw new GridifyQueryException("Filter is not defined"); } var syntaxTree = SyntaxTree.Parse(gridifyFiltering.Filter !, GridifyGlobalConfiguration.CustomOperators.Operators); if (syntaxTree.Diagnostics.Any()) { throw new GridifyFilteringException(syntaxTree.Diagnostics.Last() !); } mapper = mapper.FixMapper(syntaxTree); var(queryExpression, _) = ExpressionToQueryConvertor.GenerateQuery(syntaxTree.Root, mapper); if (queryExpression == null) { throw new GridifyQueryException("Can not create expression with current data"); } return(queryExpression); }
/// <summary> /// Validates Filter and/or OrderBy with Mappings /// </summary> /// <param name="gridifyQuery">gridify query with (Filter or OrderBy) </param> /// <param name="mapper">the gridify mapper that you want to use with, this is optional</param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static bool IsValid <T>(this IGridifyQuery gridifyQuery, IGridifyMapper <T>?mapper = null) { return(((IGridifyFiltering)gridifyQuery).IsValid(mapper) && ((IGridifyOrdering)gridifyQuery).IsValid(mapper)); }
public async static Task <QueryablePaging <T> > GridifyQueryableAsync <T> (this IQueryable <T> query, IGridifyQuery gridifyQuery, IGridifyMapper <T> mapper) { query = query.ApplyFiltering(gridifyQuery, mapper); var count = await query.CountAsync(); query = query.ApplyOrdering(gridifyQuery, mapper); query = query.ApplyPaging(gridifyQuery); return(new QueryablePaging <T> () { TotalItems = count, Query = query }); }
private static Expression <Func <T, bool> > GetExpressionFromInternalConditions <T> (IGridifyQuery gridifyQuery, IGridifyMapper <T> mapper, List <(string condition, bool IsAnd)> conditions)