NejCommon.NET/Utils/Extensions.cs
2025-01-11 19:00:51 +01:00

136 lines
6.8 KiB
C#

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<TType> ApplyPagination<TType>(this IQueryable<TType> query, Pagination pag)
{
query = query.Skip(pag.Offset);
query = query.Take(pag.Count);
return query;
}
public static async Task<PaginationResponse<TResponseType>> ApplyPaginationRes<TType, TResponseType>(this IQueryable<TType> query, IServiceProvider providers, Pagination pag) where TResponseType : IAutomappedAttribute<TType, TResponseType>, new()
{
var totalCount = await query.CountAsync();
query = query.Skip(pag.Offset);
query = query.Take(pag.Count);
var projector = new TResponseType().GetProjectorFrom(providers);
return new PaginationResponse<TResponseType>
{
TotalCount = totalCount,
Offset = pag.Offset,
Count = pag.Count,
Data = query.Select(projector).AsAsyncEnumerable()
};
}
public static async Task<PaginationResponse<TResponseType>> ApplyPaginationRes<TType, TResponseType>(this IQueryable<TType> query, IServiceProvider providers, Pagination pag, Expression<Func<TType, TResponseType>> projector) where TResponseType : IAutomappedAttribute<TType, TResponseType>, new()
{
var totalCount = await query.CountAsync();
query = query.Skip(pag.Offset);
query = query.Take(pag.Count);
return new PaginationResponse<TResponseType>
{
TotalCount = totalCount,
Offset = pag.Offset,
Count = pag.Count,
Data = query.Select(projector).AsAsyncEnumerable()
};
}
public static async Task<PaginationResponse<TResponseType>> ApplySearchPaginationRes<TType, TResponseType, TEntityBinder>(this IQueryable<TType> query, string? search, IServiceProvider providers, Pagination pag, List<Expression<Func<TType, string, bool>>> matchers)
where TType : class
where TResponseType : IAutomappedAttribute<TType, TResponseType>, new()
where TEntityBinder : EntityBinder<TType>
{
if (search != null)
{
var searchers = new List<Expression<Func<TType, bool>>>();
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<Func<TType, bool>>(redExp, par);
searchers.Add(reducedMatcher);
}
var extPar = Expression.Parameter(typeof(TType));
using (var scope = providers.CreateScope())
{
var binder = scope.ServiceProvider.GetRequiredService<TEntityBinder>();
var idMatcher = binder.RouteValues.First(x => x.Primary).Expression;
var reducedIdMatcher = Expression.Lambda<Func<TType, bool>>(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<Func<TType, bool>>(orExp, agrPar);
//Console.Writeline(orLambda);
query = query.Where(orLambda);
}
}
return await query.ApplyPaginationRes<TType, TResponseType>(providers, pag);
}
[Projectable]
public static IQueryable<TType> ApplyDateOnlyFrameQ<TType>(this IQueryable<TType> query, string datePropery, DateOnlyFrame frame) => query.Where(e => EF.Property<DateOnly>(e, datePropery) >= frame.fromDate && EF.Property<DateOnly>(e, datePropery) <= frame.toDate);
[Projectable]
public static IEnumerable<TType> ApplyDateOnlyFrameE<TType>(this ICollection<TType> query, Func<TType, DateOnly> dateAcessor, DateOnlyFrame frame) => query.Where(e => dateAcessor(e) >= frame.fromDate && dateAcessor(e) <= frame.toDate);
[Projectable]
public static IQueryable<TType> ApplyDateTimeFrameQ<TType>(this IQueryable<TType> query, string datePropery, DateTimeFrame frame) => query.Where(e => EF.Property<DateTime>(e, datePropery) >= frame.FromDate && EF.Property<DateTime>(e, datePropery) <= frame.ToDate);
[Projectable]
public static IEnumerable<TType> ApplyDateTimeFrameE<TType>(this ICollection<TType> query, Func<TType, DateTime> 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);
}