122 lines
6.1 KiB
C#
122 lines
6.1 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>> 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, Func<TType, DateOnly> dateAcessor, DateOnlyFrame frame) => query.Where(e => dateAcessor(e) >= frame.fromDate && dateAcessor(e) <= 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);
|
|
} |