Add project files.
This commit is contained in:
59
JSMR.Infrastructure/Common/Queries/SearchProvider.cs
Normal file
59
JSMR.Infrastructure/Common/Queries/SearchProvider.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace JSMR.Infrastructure.Common.Queries;
|
||||
|
||||
public abstract class SearchProvider<TItem, TCriteria, TSortField, TBaseQuery> : ISearchProvider<TItem, TCriteria, TSortField>
|
||||
where TCriteria : new()
|
||||
where TSortField : struct, Enum
|
||||
{
|
||||
public async Task<SearchResult<TItem>> SearchAsync(SearchOptions<TCriteria, TSortField> options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
IQueryable<TBaseQuery> baseQuery = GetBaseQuery();
|
||||
IQueryable<TBaseQuery> filteredQuery = ApplyFilters(baseQuery, options.Criteria);
|
||||
|
||||
int total = await filteredQuery.CountAsync(cancellationToken);
|
||||
|
||||
IOrderedQueryable<TBaseQuery> orderedQuery = ApplySorting(filteredQuery, options.SortOptions);
|
||||
IOrderedQueryable<TItem> selectQuery = GetSelectQuery(orderedQuery);
|
||||
|
||||
TItem[] items = await selectQuery
|
||||
.Skip((options.PageNumber - 1) * options.PageSize)
|
||||
.Take(options.PageSize)
|
||||
.ToArrayAsync(cancellationToken);
|
||||
|
||||
return new SearchResult<TItem>()
|
||||
{
|
||||
Items = items,
|
||||
TotalItems = total
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract IQueryable<TBaseQuery> GetBaseQuery();
|
||||
protected abstract IQueryable<TBaseQuery> ApplyFilters(IQueryable<TBaseQuery> query, TCriteria criteria);
|
||||
|
||||
private IOrderedQueryable<TBaseQuery> ApplySorting(IQueryable<TBaseQuery> query, SortOption<TSortField>[] sortOptions)
|
||||
{
|
||||
IOrderedQueryable<TBaseQuery>? ordered = null;
|
||||
|
||||
for (int i = 0; i < sortOptions.Length; i++)
|
||||
{
|
||||
var (field, direction) = (sortOptions[i].Field, sortOptions[i].Direction);
|
||||
bool isDescending = direction == SortDirection.Descending;
|
||||
|
||||
IOrderedQueryable<TBaseQuery> applyFirst(Expression<Func<TBaseQuery, object>> selector) => isDescending ? query.OrderByDescending(selector) : query.OrderBy(selector);
|
||||
IOrderedQueryable<TBaseQuery> applyNext(Expression<Func<TBaseQuery, object>> selector) => isDescending ? ordered!.ThenByDescending(selector) : ordered!.ThenBy(selector);
|
||||
|
||||
Expression<Func<TBaseQuery, object>> selector = GetSortExpression(field);
|
||||
|
||||
ordered = (i == 0) ? applyFirst(selector) : applyNext(selector);
|
||||
}
|
||||
|
||||
return ordered ?? GetDefaultSortExpression(query);
|
||||
}
|
||||
|
||||
protected abstract Expression<Func<TBaseQuery, object>> GetSortExpression(TSortField field);
|
||||
protected abstract IOrderedQueryable<TBaseQuery> GetDefaultSortExpression(IQueryable<TBaseQuery> query);
|
||||
protected abstract IOrderedQueryable<TItem> GetSelectQuery(IOrderedQueryable<TBaseQuery> query);
|
||||
}
|
||||
Reference in New Issue
Block a user