WebApi + ClientApp, GraphQL, Reflection

This commit is contained in:
Boris Milašinović
2026-05-06 20:55:05 +02:00
parent 8f7c704a90
commit 4fb3de19f6
196 changed files with 10395 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
using AutoMapper;
using Events.WebAPI.Contract.DTOs;
using Events.WebAPI.Contract.Queries.Generic;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Sieve.Models;
using Sieve.Services;
namespace Events.WebAPI.Handlers.EF.QueryHandlers.Generic
{
public abstract class GenericQueryHandler<TDto, TDal, TPK> :
IRequestHandler<GetSingleItemQuery<TDto, TPK>, TDto?>,
IRequestHandler<GetCountQuery<TDto>, int>,
IRequestHandler<DoesItemExistsQuery<TDto, TPK>, bool>,
IRequestHandler<GetItemsQuery<TDto>, List<TDto>>
where TDal : class, IHasIdAsPK<TPK>
where TPK : IEquatable<TPK>
{
private readonly DbContext ctx;
protected readonly ILogger logger;
private readonly IMapper mapper;
private readonly ISieveProcessor sieveProcessor;
public GenericQueryHandler(DbContext ctx, ILogger logger, IMapper mapper, ISieveProcessor sieveProcessor)
{
this.ctx = ctx;
this.logger = logger;
this.mapper = mapper;
this.sieveProcessor = sieveProcessor;
}
public virtual async Task<int> Handle(GetCountQuery<TDto> request, CancellationToken cancellationToken)
{
var query = ctx.Set<TDal>().AsNoTracking();
IQueryable<TDto> projectedQuery = mapper.ProjectTo<TDto>(query);
SieveModel sieveModel = new SieveModel()
{
Filters = request.Filters,
};
var filteredQuery = sieveProcessor.Apply(sieveModel, projectedQuery, applyFiltering: true, applySorting: false, applyPagination: false);
int count = await filteredQuery.CountAsync(cancellationToken);
return count;
}
public virtual async Task<TDto?> Handle(GetSingleItemQuery<TDto, TPK> request, CancellationToken cancellationToken)
{
var query = ctx.Set<TDal>()
.AsNoTracking()
.Where(t => t.Id.Equals(request.Id));
IQueryable<TDto> projectedQuery = mapper.ProjectTo<TDto>(query);
var item = await projectedQuery.FirstOrDefaultAsync(cancellationToken);
return item;
}
public virtual async Task<bool> Handle(DoesItemExistsQuery<TDto, TPK> request, CancellationToken cancellationToken)
{
var query = ctx.Set<TDal>()
.AsNoTracking()
.Where(t => t.Id.Equals(request.Id));
bool exists = await query.AnyAsync(cancellationToken);
return exists;
}
public virtual async Task<List<TDto>> Handle(GetItemsQuery<TDto> request, CancellationToken cancellationToken)
{
var query = ctx.Set<TDal>().AsNoTracking();
IQueryable<TDto> projectedQuery = mapper.ProjectTo<TDto>(query);
SieveModel sieveModel = new SieveModel()
{
Filters = request.Filters,
Sorts = BuildSortExpression(request),
PageSize = request.PageSize,
Page = request.Page
};
var filteredQuery = sieveProcessor.Apply(sieveModel, projectedQuery, applyFiltering: true, applySorting: true, applyPagination: true);
var data = await filteredQuery.ToListAsync(cancellationToken);
return data;
}
private static string? BuildSortExpression(GetItemsQuery<TDto> request)
{
if (!string.IsNullOrWhiteSpace(request.Sort))
{
return request.Ascending ? request.Sort : "-" + request.Sort;
}
bool paginationRequested = request.Page.HasValue || request.PageSize.HasValue;
return paginationRequested ? nameof(IHasIdAsPK<int>.Id) : null;
}
}
}