分页排序和多条件查询
This commit is contained in:
1 parent
62a8b7f569
commit
6fef1a9ea0
7 files changed
+161
-16
No files matched your search
@@ -0,0 +1,78 @@
|
||||
using HelloShop.ServiceDefaults.Constants;
|
||||
using HelloShop.ServiceDefaults.Models.Paging;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace HelloShop.ServiceDefaults.Extensions;
|
||||
|
||||
public static class QueryableExtensions
|
||||
{
|
||||
public static IQueryable<TEntity> SortBy<TEntity>(this IQueryable<TEntity> query, string? orderBy = null)
|
||||
{
|
||||
PropertyInfo[] properties = typeof(TEntity).GetProperties();
|
||||
|
||||
IOrderedQueryable<TEntity>? orderedQueryable = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(orderBy))
|
||||
{
|
||||
// Convert expressions of the form field1 desc,field2 asc
|
||||
|
||||
string[] orderBySubs = orderBy.Split(',');
|
||||
|
||||
foreach (var orderBySub in orderBySubs)
|
||||
{
|
||||
string[] orderByParts = orderBySub.Trim().Split(' ');
|
||||
|
||||
if (orderByParts.Length >= 1)
|
||||
{
|
||||
string propertyName = PascalCaseNamingPolicy.PascalCase.ConvertName(orderByParts[0]);
|
||||
|
||||
bool ascending = orderByParts.Length == 1 || (orderByParts.Length == 2 && orderByParts[1].Equals("asc", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (properties.Any(x => x.Name == propertyName))
|
||||
{
|
||||
if (ascending)
|
||||
{
|
||||
orderedQueryable = orderedQueryable is null ? query.OrderBy(propertyName) : orderedQueryable.ThenBy(propertyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
orderedQueryable = orderedQueryable is null ? query.OrderByDescending(propertyName) : orderedQueryable.ThenByDescending(propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (orderedQueryable is null)
|
||||
{
|
||||
string defaultPropertyName = properties.Any(x => x.Name == EntityConnstants.DefaultKey) ? EntityConnstants.DefaultKey : properties.First().Name;
|
||||
|
||||
orderedQueryable = query.OrderByDescending(defaultPropertyName);
|
||||
}
|
||||
|
||||
return orderedQueryable;
|
||||
}
|
||||
|
||||
public static IQueryable<TEntity> PageBy<TEntity>(this IQueryable<TEntity> query, PagedRequest pagedRequest)
|
||||
{
|
||||
return query.Skip((pagedRequest.PageNumber - 1) * pagedRequest.PageSize).Take(pagedRequest.PageSize);
|
||||
}
|
||||
|
||||
public static IQueryable<TEntity> SortAndPageBy<TEntity>(this IQueryable<TEntity> query, PagedAndSortedRequest? pagedAndSortedRequest = null)
|
||||
{
|
||||
pagedAndSortedRequest ??= new PagedAndSortedRequest { PageNumber = 1, PageSize = PagingConstants.DefaultPageSize };
|
||||
|
||||
return query.SortBy(pagedAndSortedRequest.OrderBy).PageBy(pagedAndSortedRequest);
|
||||
}
|
||||
|
||||
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, bool>> predicate)
|
||||
{
|
||||
return condition ? source.Where(predicate) : source;
|
||||
}
|
||||
|
||||
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, int, bool>> predicate)
|
||||
{
|
||||
return condition ? source.Where(predicate) : source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace HelloShop.ServiceDefaults.Extensions;
|
||||
|
||||
public static class QueryableOrderByExtensions
|
||||
{
|
||||
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName) => OrderingHelper<T>.OrderBy(source, propertyName);
|
||||
|
||||
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName) => OrderingHelper<T>.OrderByDescending(source, propertyName);
|
||||
|
||||
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName) => OrderingHelper<T>.ThenBy(source, propertyName);
|
||||
|
||||
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string propertyName) => OrderingHelper<T>.ThenByDescending(source, propertyName);
|
||||
|
||||
private static class OrderingHelper<TSource>
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, LambdaExpression> cached = new();
|
||||
|
||||
public static IOrderedQueryable<TSource> OrderBy(IQueryable<TSource> source, string propertyName) => Queryable.OrderBy(source, (dynamic)CreateLambdaExpression(propertyName));
|
||||
|
||||
public static IOrderedQueryable<TSource> OrderByDescending(IQueryable<TSource> source, string propertyName) => Queryable.OrderByDescending(source, (dynamic)CreateLambdaExpression(propertyName));
|
||||
|
||||
public static IOrderedQueryable<TSource> ThenBy(IOrderedQueryable<TSource> source, string propertyName) => Queryable.ThenBy(source, (dynamic)CreateLambdaExpression(propertyName));
|
||||
|
||||
public static IOrderedQueryable<TSource> ThenByDescending(IOrderedQueryable<TSource> source, string propertyName) => Queryable.ThenByDescending(source, (dynamic)CreateLambdaExpression(propertyName));
|
||||
|
||||
private static LambdaExpression CreateLambdaExpression(string propertyName)
|
||||
{
|
||||
if (cached.TryGetValue(propertyName, out LambdaExpression? value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
var parameter = Expression.Parameter(typeof(TSource));
|
||||
var body = Expression.Property(parameter, propertyName);
|
||||
var keySelector = Expression.Lambda(body, parameter);
|
||||
|
||||
cached[propertyName] = keySelector;
|
||||
|
||||
return keySelector;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace HelloShop.ServiceDefaults;
|
||||
|
||||
public class PascalCaseNamingPolicy : JsonNamingPolicy
|
||||
{
|
||||
public static PascalCaseNamingPolicy PascalCase { get; } = new PascalCaseNamingPolicy();
|
||||
|
||||
public override string ConvertName(string name) => string.Concat(char.ToUpper(name[0]), name[1..]);
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
public class PagedAndSortedRequest : PagedRequest
|
||||
{
|
||||
public IEnumerable<SortingOrder>? Sorts { get; init; }
|
||||
}
|
||||
public string? OrderBy { get; init; }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace HelloShop.ServiceDefaults.Models.Paging;
|
||||
|
||||
public class SortingOrder
|
||||
{
|
||||
public required string PropertyName { get; init; }
|
||||
|
||||
public bool Ascending { get; init; }
|
||||
}
|
||||
Reference in new issue
Block a user