diff --git a/src/EFCoreQueryMagic/EFCoreQueryMagic.csproj b/src/EFCoreQueryMagic/EFCoreQueryMagic.csproj index 889a0c5..a691722 100644 --- a/src/EFCoreQueryMagic/EFCoreQueryMagic.csproj +++ b/src/EFCoreQueryMagic/EFCoreQueryMagic.csproj @@ -8,7 +8,7 @@ Readme.md PandaTech MIT - 1.0.0 + 1.0.1 Pandatech.EFCoreQueryMagic Pandatech.EFCoreQueryMagic: Dynamic Query and Filter Generator for EF Core Unlock the full potential of your Entity Framework Core applications with Pandatech.EFCoreQueryMagic. This innovative package empowers developers to seamlessly create dynamic, complex queries and filters for SQL tables without diving deep into the intricacies of LINQ or manual query construction. Designed to enhance productivity and maintainability, EFCoreQueryMagic automates the translation of front-end filter requests into optimized, ready-to-execute EF Core queries. Embrace the magic of streamlined data retrieval and manipulation, and elevate your applications to new heights of efficiency and performance. diff --git a/src/EFCoreQueryMagic/Extensions/DistinctColumnValuesExtensions.cs b/src/EFCoreQueryMagic/Extensions/DistinctColumnValuesExtensions.cs index 07d9f5b..c7446a8 100644 --- a/src/EFCoreQueryMagic/Extensions/DistinctColumnValuesExtensions.cs +++ b/src/EFCoreQueryMagic/Extensions/DistinctColumnValuesExtensions.cs @@ -64,22 +64,9 @@ public static DistinctColumnValues DistinctColumnValues(this IQueryable< var propertyType = PropertyHelper.GetPropertyType(typeof(TModel), mappedToPropertyAttribute); - if (propertyType.EnumCheck()) - { - var values = Enum.GetValues(GetEnumerableType(propertyType)).Cast() - .Where(x => !(x as Enum)!.HasAttributeOfType()); - - var list = values.ToList(); - result.Values = list.Paginate(pageSize, page); - result.TotalCount = list.Count; - return result; - } - var query = GenerateBaseQueryable(dbSet, filters, context); IQueryable query2; - // check for ICollection<> - var property = PropertyHelper.GetPropertyLambda(mappedToPropertyAttribute); if (propertyType.IsIEnumerable() && !mappedToPropertyAttribute.Encrypted) @@ -96,16 +83,26 @@ public static DistinctColumnValues DistinctColumnValues(this IQueryable< : Activator.CreateInstance(mappedToPropertyAttribute.ConverterType ?? typeof(DirectConverter))) as IConverter; - converter.Context = context; + converter!.Context = context; var method = converter.GetType().GetMethods().First(x => x.Name == "ConvertFrom"); var query3 = query2.Distinct(); - + + if (propertyType.EnumCheck()) + { + var excludedValues = Enum.GetValues(GetEnumerableType(propertyType)).Cast() + .Where(x => (x as Enum)!.HasAttributeOfType()) + .ToList(); + + if (excludedValues.Count != 0) + query3 = query3.Where(x => !excludedValues.Contains(x)); + } + result.Values = query3.Skip(pageSize * (page - 1)).Take(pageSize) .ToList() .Select(x => method.Invoke(converter, [x])!).Distinct().OrderBy(x => x).ToList(); - + try { result.TotalCount = mappedToPropertyAttribute.Encrypted ? 1 : query3.LongCount(); @@ -139,22 +136,9 @@ public static async Task DistinctColumnValuesAsync var propertyType = PropertyHelper.GetPropertyType(typeof(TModel), mappedToPropertyAttribute); - if (propertyType.EnumCheck()) - { - var values = Enum.GetValues(GetEnumerableType(propertyType)).Cast() - .Where(x => !(x as Enum)!.HasAttributeOfType()); - - var list = values.ToList(); - result.Values = list.Paginate(pageSize, page); - result.TotalCount = list.Count; - return result; - } - var query = GenerateBaseQueryable(dbSet, filters, context); IQueryable query2; - // check for ICollection<> - var property = PropertyHelper.GetPropertyLambda(mappedToPropertyAttribute); if (propertyType.IsIEnumerable() && !mappedToPropertyAttribute.Encrypted) @@ -171,16 +155,26 @@ public static async Task DistinctColumnValuesAsync : Activator.CreateInstance(mappedToPropertyAttribute.ConverterType ?? typeof(DirectConverter))) as IConverter; - converter.Context = context; + converter!.Context = context; var method = converter.GetType().GetMethods().First(x => x.Name == "ConvertFrom"); var query3 = query2.Distinct(); - + + if (propertyType.EnumCheck()) + { + var excludedValues = Enum.GetValues(GetEnumerableType(propertyType)).Cast() + .Where(x => (x as Enum)!.HasAttributeOfType()) + .ToList(); + + if (excludedValues.Count != 0) + query3 = query3.Where(x => !excludedValues.Contains(x)); + } + result.Values = (await query3.Skip(pageSize * (page - 1)).Take(pageSize) .ToListAsync(cancellationToken: cancellationToken)) .Select(x => method.Invoke(converter, [x])!).Distinct().OrderBy(x => x).ToList(); - + try { result.TotalCount = mappedToPropertyAttribute.Encrypted diff --git a/src/EFCoreQueryMagic/Extensions/FilterExtensions.cs b/src/EFCoreQueryMagic/Extensions/FilterExtensions.cs index cb09d42..87ad677 100644 --- a/src/EFCoreQueryMagic/Extensions/FilterExtensions.cs +++ b/src/EFCoreQueryMagic/Extensions/FilterExtensions.cs @@ -12,7 +12,6 @@ namespace EFCoreQueryMagic.Extensions; public static class FilterExtensions { - //public static IQueryable ApplyFilters(this IQueryable dbSet, List filters) public static IQueryable ApplyFilters(this IQueryable dbSet, List filters, DbContext? context = null) { @@ -35,12 +34,6 @@ public static IQueryable ApplyFilters(this IQueryable db var targetType = PropertyHelper.GetPropertyType(typeof(TModel), mappedToPropertyAttribute); if (targetType.IsIEnumerable() && !mappedToPropertyAttribute.Encrypted) targetType = targetType.GetCollectionType(); - - // var nullabilityContext = new NullabilityInfoContext(); - // if (nullabilityContext.Create(filterProperty).ReadState == NullabilityState.Nullable) - // { - // Convert.ChangeType(targetType, Nullable); - // } var method = typeof(PropertyHelper).GetMethod("GetValues")!.MakeGenericMethod(targetType); diff --git a/src/EFCoreQueryMagic/Helpers/PropertyHelper.cs b/src/EFCoreQueryMagic/Helpers/PropertyHelper.cs index 090214f..540a06d 100644 --- a/src/EFCoreQueryMagic/Helpers/PropertyHelper.cs +++ b/src/EFCoreQueryMagic/Helpers/PropertyHelper.cs @@ -1,5 +1,4 @@ using System.Linq.Expressions; -using System.Reflection; using System.Text.Json; using EFCoreQueryMagic.Attributes; using EFCoreQueryMagic.Converters; @@ -69,7 +68,12 @@ public static List GetValues(this FilterDto filter, MappedToPropertyAttrib } if (typeof(T).EnumCheck()) - return (T)Enum.Parse(typeof(T).GetEnumType(), val.GetString()!, true); + { + if (val.ValueKind == JsonValueKind.String) + return (T)Enum.Parse(typeof(T).GetEnumType(), val.GetString()!, true); + + return (T)Enum.ToObject(typeof(T), val.GetInt32()); + } var type = attribute.Encrypted ? typeof(string) : typeof(T); diff --git a/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumNullableTests.cs b/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumNullableTests.cs index dee5588..d7003a0 100644 --- a/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumNullableTests.cs +++ b/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumNullableTests.cs @@ -1,4 +1,5 @@ using EFCoreQueryMagic.Dto; +using EFCoreQueryMagic.Enums; using EFCoreQueryMagic.Extensions; using EFCoreQueryMagic.Test.EntityFilters; using EFCoreQueryMagic.Test.Enums; @@ -17,9 +18,9 @@ public void TestDistinctColumnValuesAsync() { var set = _context.Orders; - var query = System.Enum.GetValues() - .Select(x => x as object) - .OrderBy(x => x) + var query = set + .Select(x => x.CancellationStatus as object) + .OrderBy(x => (int)x) .ToList(); var qString = new GetDataRequest(); @@ -29,14 +30,71 @@ public void TestDistinctColumnValuesAsync() query.Should().Equal(result.Values); } + [Fact] + public void TestDistinctColumnValuesAsync_String() + { + var set = _context.Orders; + + var query = set + .Where(x => x.CancellationStatus == CancellationStatus.Yes) + .Select(x => x.CancellationStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [CancellationStatus.Yes.ToString()], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.CancellationStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.CancellationStatus), 20, 1); + + query.Should().Equal(result.Values); + } + + [Fact] + public void TestDistinctColumnValuesAsync_Number() + { + var set = _context.Orders; + + var query = set + .Where(x => x.CancellationStatus == CancellationStatus.Yes) + .Select(x => x.CancellationStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [(int)CancellationStatus.Yes], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.CancellationStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.CancellationStatus), 20, 1); + + query.Should().Equal(result.Values); + } + + [Fact] public void TestDistinctColumnValues() { var set = _context.Orders; - var query = System.Enum.GetValues() - .Select(x => x as object) - .OrderBy(x => x) + var query = set + .Select(x => x.CancellationStatus as object) + .OrderBy(x => (int)x) .ToList(); var qString = new GetDataRequest(); @@ -45,4 +103,60 @@ public void TestDistinctColumnValues() query.Should().Equal(result.Values); } + + [Fact] + public void TestDistinctColumnValues_String() + { + var set = _context.Orders; + + var query = set + .Where(x => x.CancellationStatus == CancellationStatus.Yes) + .Select(x => x.CancellationStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [CancellationStatus.Yes.ToString()], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.CancellationStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.CancellationStatus), 20, 1); + + query.Should().Equal(result.Values); + } + + [Fact] + public void TestDistinctColumnValues_Number() + { + var set = _context.Orders; + + var query = set + .Where(x => x.CancellationStatus == CancellationStatus.Yes) + .Select(x => x.CancellationStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [(int)CancellationStatus.Yes], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.CancellationStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.CancellationStatus), 20, 1); + + query.Should().Equal(result.Values); + } } \ No newline at end of file diff --git a/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumTests.cs b/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumTests.cs index 613e8ad..b25a021 100644 --- a/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumTests.cs +++ b/test/EFCoreQueryMagic.Test/DistinctTests/Enum/EnumTests.cs @@ -1,4 +1,5 @@ using EFCoreQueryMagic.Dto; +using EFCoreQueryMagic.Enums; using EFCoreQueryMagic.Extensions; using EFCoreQueryMagic.Test.EntityFilters; using EFCoreQueryMagic.Test.Enums; @@ -11,36 +12,151 @@ namespace EFCoreQueryMagic.Test.DistinctTests.Enum; public class EnumTests(DatabaseFixture fixture) { private readonly TestDbContext _context = fixture.Context; - + [Fact] public void TestDistinctColumnValuesAsync() { var set = _context.Orders; - var query = System.Enum.GetValues() - .Select(x => x as object) + var query = set + .Select(x => x.PaymentStatus as object) + .OrderBy(x => (int)x) .ToList(); - + var qString = new GetDataRequest(); var result = set.DistinctColumnValuesAsync(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1).Result; - + + query.Should().Equal(result.Values); + } + + [Fact] + public void TestDistinctColumnValuesAsync_String() + { + var set = _context.Orders; + + var query = set + .Where(x => x.PaymentStatus == PaymentStatus.Pending) + .Select(x => x.PaymentStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [PaymentStatus.Pending.ToString()], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.PaymentStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1); + query.Should().Equal(result.Values); } - + + [Fact] + public void TestDistinctColumnValuesAsync_Number() + { + var set = _context.Orders; + + var query = set + .Where(x => x.PaymentStatus == PaymentStatus.Pending) + .Select(x => x.PaymentStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [(int)PaymentStatus.Pending], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.PaymentStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1); + + query.Should().Equal(result.Values); + } + + [Fact] public void TestDistinctColumnValues() { var set = _context.Orders; - var query = System.Enum.GetValues() - .Select(x => x as object) + var query = set + .Select(x => x.PaymentStatus as object) + .OrderBy(x => (int)x) .ToList(); - + var qString = new GetDataRequest(); var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1); - + + query.Should().Equal(result.Values); + } + + [Fact] + public void TestDistinctColumnValues_String() + { + var set = _context.Orders; + + var query = set + .Where(x => x.PaymentStatus == PaymentStatus.Pending) + .Select(x => x.PaymentStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [PaymentStatus.Pending.ToString()], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.PaymentStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1); + + query.Should().Equal(result.Values); + } + + [Fact] + public void TestDistinctColumnValues_Number() + { + var set = _context.Orders; + + var query = set + .Where(x => x.PaymentStatus == PaymentStatus.Pending) + .Select(x => x.PaymentStatus as object) + .ToList(); + + var qString = GetDataRequest.FromString(new GetDataRequest + { + Filters = + [ + new FilterDto + { + Values = [(int)PaymentStatus.Pending], + ComparisonType = ComparisonType.Equal, + PropertyName = nameof(OrderFilter.PaymentStatus) + } + ] + }.ToString()); + + var result = set.DistinctColumnValues(qString.Filters, nameof(OrderFilter.PaymentStatus), 20, 1); + query.Should().Equal(result.Values); } } \ No newline at end of file