/// <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 void NestedFiltering_OnChildElement_ShouldWorkOnExecution() { // Arrange var testList = new List <Root>() { new() { Child1 = new Child1 { Child2List = new List <Child2>() { new() { Name = "name" } } } }, new() { Child1 = new Child1 { Child2List = new List <Child2>() { new() { Name = "name2" } } } }, }; ; var mapping = new GridifyMapper <Root>() .AddMap("x1", x => x.Child1.Child2List.Select(c => c.Name)); // ReSharper disable once ConditionIsAlwaysTrueOrFalse Expression <Func <Root, bool> > expectedExpression = x => (x.Child1.Child2List != null) && (x.Child1.Child2List.Any(c => c.Name == "name")); var expected = testList.AsQueryable().Where(expectedExpression).ToList(); // Act var actual = testList.AsQueryable().ApplyFiltering("x1=name", mapping).ToList(); // Assert Assert.Equal(expected, actual); Assert.NotEmpty(actual); }
public void ApplyFiltering_ShadowProperty() { var gm = new GridifyMapper <User>() .AddMap("x", (User q) => EF.Property <string>(q, "shadow1")); var expected = _dbContext.Users.Where(q => EF.Property <string>(q, "shadow1") == "test").ToQueryString(); var actual = _dbContext.Users.ApplyFiltering("x = test", gm).ToQueryString(); Assert.Equal(expected, actual); }
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); }
[Fact] // issue #29 https://github.com/alirezanet/Gridify/issues/29 public void ApplyFiltering_UsingSubCollection_PassIndexes() { var gm = new GridifyMapper <Level2>() .GenerateMappings() .AddMap("l3p2", (l1, index) => l1.Level3List[index].Property2); var expected = _fakeRepository2Nesting.Where(q => q.Level3List[0].Property2 > 50).ToList(); var actual = _fakeRepository2Nesting.AsQueryable().ApplyFiltering("l3p2[1] > 50", gm).ToList(); Assert.Equal(expected.Count, actual.Count); Assert.Equal(expected, actual); Assert.True(actual.Any()); }
public void CustomOperator_EFJsonContains_ShouldGenerateCorrectExpression() { // Arrange GridifyGlobalConfiguration.CustomOperators.Register(new JsonContainsOperator()); var gm = new GridifyMapper <Products>() .AddMap("u", q => q.Users); var expected = _dbContext.ProductsViews.Where(q => EF.Functions.JsonContains(q.Users, new[] { new { Id = 1 } })).ToQueryString(); // Act var actual = _dbContext.ProductsViews.ApplyFiltering("u #= 1", gm).ToQueryString(); // Assert Assert.Equal(expected, actual); }
public void NestedFiltering_OnChildElement_ShouldNotThrowException() { // Arrange var mapping = new GridifyMapper <Root>() .AddMap("Child2Name", x => x.Child2List.Select(c => c.Name)) // Works fine .AddMap("Child2NameNested", x => x.Child1.Child2List.Select(c => c.Name)); // Throws exception // Act var exp = new GridifyQuery { Filter = "Child2NameNested=name" }.GetFilteringExpression(mapping); // Assert Assert.NotNull(exp); }
public void Filtering_OnThirdLevelNestedProperty() { var gm = new GridifyMapper <Level1>() .GenerateMappings() .AddMap("prop1", l1 => l1.Level2List.SelectMany(l2 => l2.Level3List).Select(l3 => l3.Property1)); var actual = _fakeRepository3Nesting.AsQueryable() .ApplyFiltering("prop1 <= 3", gm) .ToList(); var expected = _fakeRepository3Nesting.Where(q => q.Level2List.Any(w => w.Level3List.Any(z => z.Property1 <= 3))).ToList(); Assert.Equal(expected.Count, actual.Count); Assert.Equal(expected, actual); Assert.True(actual.Any()); }
public void Filtering_OnThirdLevelNestedPropertyUsingSecondLevelProp() { var gm = new GridifyMapper <Level1>() .GenerateMappings() .AddMap("lvl", l1 => l1.Level2List.Select(l2 => l2.ChildProp).SelectMany(sl2 => sl2.Level3List).Select(l3 => l3.Level)); var actual = _fakeRepository3Nesting.AsQueryable() .ApplyFiltering("lvl < 2", gm) .ToList(); var expected = _fakeRepository3Nesting.Where(l1 => l1.Level2List != null && l1.Level2List.Any(l2 => l2.ChildProp != null && l2.ChildProp.Level3List != null && l2.ChildProp.Level3List.Any(l3 => l3.Level < 2))).ToList(); Assert.Equal(expected.Count, actual.Count); Assert.Equal(expected, actual); Assert.True(actual.Any()); }
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 void NestedFiltering_OnChildElement_ShouldReturnAValidExpression() { // Arrange var mapping = new GridifyMapper <Root>() .AddMap("x1", x => x.Child1.Child2List.Select(c => c.Name)); // ReSharper disable once ConditionIsAlwaysTrueOrFalse Expression <Func <Root, bool> > expectedExpression = x => (x.Child1.Child2List != null) && (x.Child1.Child2List.Any(c => c.Name == "name")); var expected = expectedExpression.ToString(); // Act var actual = new GridifyQuery { Filter = "x1=name" }.GetFilteringExpression(mapping).ToString(); // Assert // "x => ((x.Child1.Child2List != null) AndAlso x.Child1.Child2List.Any(c => (c.Name == \"name\")))"; Assert.Equal(expected, actual); }
public void Filtering_OnThirdLevelNestedPropertyWithMultipleUnChainedConditionsWithNestedParenthesis() { var gm = new GridifyMapper <Level1>() .GenerateMappings() .AddMap("Level2List_Level3List_Property1", l1 => l1.Level2List.SelectMany(l2 => l2.Level3List).Select(l3 => l3.Property1)) .AddMap("Level2List_Id", l1 => l1.Level2List.Select(l2 => l2.Id)); var actual = _fakeRepository3Nesting.AsQueryable() .ApplyFiltering("( (id < 10 ), Level2List_Id = 101, Level2List_Level3List_Property1 >= 3)", gm) .ToList(); var expected = _fakeRepository3Nesting.AsQueryable().Where( l1 => l1.Level2List != null && l1.Level2List.Any(l2 => l2.Id == 101) && l1.Level2List.Any(l2 => l2.Level3List.Any(l3 => l3.Property1 >= 3))).ToList(); Assert.Equal(expected.Count, actual.Count); Assert.Equal(expected, actual); Assert.True(actual.Any()); }
public async Task <IActionResult> GetCustomMappedList([FromQuery] GridifyQuery gridifyQuery) { // Case sensetive is false by default. But we can enable it here. var customMappings = new GridifyMapper <Person>(false) // Because properties with same name exists in both DTO and Entity classes, we can generate them. .GenerateMappings() // Add custom mappings .AddMap("livingAddress", q => q.Contact.Address) .AddMap("phone", q => q.Contact.PhoneNumber.ToString()); // GridifyQueryable return a QueryablePaging<T> var result = await _context.People.GridifyQueryableAsync(gridifyQuery, customMappings); // We then apply AutoMapper to the query result and return a Paging. return(Ok(new Paging <PersonDto>() { Items = result.Query.ProjectTo <PersonDto>(_mapper.ConfigurationProvider).ToList(), TotalItems = result.TotalItems })); }
private void UserReportTest1() { List <Level1> level1List = new List <Level1>(); level1List.Add(new Level1()); var gridifyMapper = new GridifyMapper <Level1>().GenerateMappings() .AddMap("level4_property1", (l1, index) => l1.Level2List.Select(x => x.Level3.Level4List[index].Property1)); var gridifyQuery = new GridifyQuery() { Filter = "level4_property1[0] > 5" }; var query = gridifyQuery.GetFilteringExpression(gridifyMapper); var expression = query.Compile(); var actual = level1List.Where(expression).ToList(); Assert.Single(actual); Assert.True(actual.Any()); }
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) !); } } }