using System.Globalization; using System.Linq.Expressions; using AutoMapPropertyHelper; using EntityFrameworkCore.Projectables; using EntityFrameworkCore.Projectables.Extensions; using Microsoft.EntityFrameworkCore; using NejCommon.Controllers; using NejCommon.Models; namespace NejCommon.Utils; public static class Extensions { public static IQueryable ApplyPagination(this IQueryable query, Pagination pag) { query = query.Skip(pag.Offset); query = query.Take(pag.Count); return query; } public static async Task> ApplyPaginationRes(this IQueryable query, IServiceProvider providers, Pagination pag, Expression>? projector = null, CancellationToken cancellationToken = default) where TResponseType : IAutomappedAttribute, new() { var totalCount = await query.CountAsync(cancellationToken); query = query.Skip(pag.Offset); query = query.Take(pag.Count); if (projector == null) projector = new TResponseType().GetProjectorFrom(providers); return new PaginationResponse { TotalCount = totalCount, Offset = pag.Offset, Count = pag.Count, Data = query.Select(projector).AsAsyncEnumerable() }; } public static async Task> ApplySearchPaginationRes(this IQueryable query, string? search, IServiceProvider providers, Pagination pag, List>> matchers, Expression>? projector = null, CancellationToken cancellationToken = default) where TType : class where TResponseType : IAutomappedAttribute, new() where TEntityBinder : EntityBinder { if (search != null) { var searchers = new List>>(); foreach (var matcher in matchers) { //reduce expression from TType, string, bool to TType, bool by passing the search string var par = Expression.Parameter(typeof(TType)); var exp = Expression.Invoke(matcher, par, Expression.Constant(search)); var redExp = exp.Reduce(); var reducedMatcher = Expression.Lambda>(redExp, par); searchers.Add(reducedMatcher); } var extPar = Expression.Parameter(typeof(TType)); using (var scope = providers.CreateScope()) { var binder = scope.ServiceProvider.GetRequiredService(); var idMatcher = binder.RouteValues.First(x => x.Primary).Expression; var reducedIdMatcher = Expression.Lambda>(Expression.Invoke(idMatcher, extPar, Expression.Constant(search)).Reduce(), extPar); //Console.Writeline(reducedIdMatcher); searchers.Add(reducedIdMatcher); // Create an expression that ORs all the searchers var agrPar = Expression.Parameter(typeof(TType)); var orExp = searchers.Aggregate((Expression)null, (current, searcher) => { var body = Expression.Invoke(searcher, agrPar); if (current == null) { return body; } return Expression.OrElse(current, body); }); //reduce the epxression as much as possible while (orExp.CanReduce) { orExp = orExp.Reduce(); } var orLambda = Expression.Lambda>(orExp, agrPar); //Console.Writeline(orLambda); query = query.Where(orLambda); } } return await query.ApplyPaginationRes(providers, pag, projector, cancellationToken); } [Projectable] public static IQueryable ApplyDateOnlyFrameQ(this IQueryable query, string datePropery, DateOnlyFrame frame) => query.Where(e => EF.Property(e, datePropery) >= frame.fromDate && EF.Property(e, datePropery) <= frame.toDate); [Projectable] public static IEnumerable ApplyDateOnlyFrameE(this ICollection query, Func dateAcessor, DateOnlyFrame frame) => query.Where(e => dateAcessor(e) >= frame.fromDate && dateAcessor(e) <= frame.toDate); [Projectable] public static IQueryable ApplyDateTimeFrameQ(this IQueryable query, string datePropery, DateTimeFrame frame) => query.Where(e => EF.Property(e, datePropery) >= frame.FromDate && EF.Property(e, datePropery) <= frame.ToDate); [Projectable] public static IEnumerable ApplyDateTimeFrameE(this ICollection query, Func dateAcessor, DateTimeFrame frame) => query.Where(e => dateAcessor(e) >= frame.FromDate && dateAcessor(e) <= frame.ToDate); [Projectable] public static DateOnly ToDateOnly(this DateTime date) => new DateOnly(date.Year, date.Month, date.Day); [Projectable] public static DateTime ToDateTime(this DateOnly date) => new DateTime(date.Year, date.Month, date.Day); [Projectable] public static decimal Round(this decimal value, int decimals = 2) => Math.Round(value, decimals); [Projectable] public static decimal Floor(this decimal value, int decimals = 2) => Math.Floor(value * (decimal)Math.Pow(10, decimals)) / (decimal)Math.Pow(10, decimals); [Projectable] public static int RountToInt(this decimal value) => (int)Math.Round(value); [Projectable] public static int GetInt(this string value, NumberStyles? style = null, CultureInfo? culture = null) => int.Parse(value, style ?? NumberStyles.Number, culture ?? CultureInfo.InvariantCulture); [Projectable] public static decimal GetDecimal(this string value, NumberStyles? style = null, CultureInfo? culture = null) => decimal.Parse(value, style ?? NumberStyles.Number, culture ?? CultureInfo.InvariantCulture); [Projectable] public static float GetFloat(this string value, NumberStyles? style = null, CultureInfo? culture = null) => float.Parse(value, style ?? NumberStyles.Number, culture ?? CultureInfo.InvariantCulture); }