WebApi + ClientApp, GraphQL, Reflection
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Contract.LookupQueries;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class CountriesLookupQueryHandler : IRequestHandler<LookupCountryQuery, List<IdName<string>>>
|
||||
{
|
||||
private readonly EventsContext ctx;
|
||||
|
||||
public CountriesLookupQueryHandler(EventsContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public async Task<List<IdName<string>>> Handle(LookupCountryQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = ctx.Countries.AsNoTracking();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.Text))
|
||||
{
|
||||
string text = request.Text.Trim();
|
||||
query = query.Where(c => Microsoft.EntityFrameworkCore.EF.Functions.ILike(c.Name, $"%{text}%"));
|
||||
}
|
||||
|
||||
return await query
|
||||
.OrderBy(c => c.Name)
|
||||
.Select(c => new IdName<string>
|
||||
{
|
||||
Id = c.Code,
|
||||
Name = c.Name
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using AutoMapper;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using Events.WebAPI.Handlers.EF.Models;
|
||||
using Events.WebAPI.Handlers.EF.QueryHandlers.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sieve.Services;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class EventsQueryHandler : GenericQueryHandler<EventDTO, Event, int>
|
||||
{
|
||||
public EventsQueryHandler(EventsContext ctx, ILogger<EventsQueryHandler> logger, IMapper mapper, ISieveProcessor sieveProcessor)
|
||||
: base(ctx, logger, mapper, sieveProcessor)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Contract.LookupQueries;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class PeopleLookupQueryHandler : IRequestHandler<LookupPeopleQuery, List<IdName<int>>>
|
||||
{
|
||||
private readonly EventsContext ctx;
|
||||
|
||||
public PeopleLookupQueryHandler(EventsContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public async Task<List<IdName<int>>> Handle(LookupPeopleQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = ctx.People.AsNoTracking();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.Text))
|
||||
{
|
||||
string text = request.Text.Trim();
|
||||
query = query.Where(p =>
|
||||
global::Microsoft.EntityFrameworkCore.EF.Functions.ILike(
|
||||
p.FirstNameTranscription + " " + p.LastNameTranscription,
|
||||
$"%{text}%"));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.CountryCode))
|
||||
{
|
||||
string countryCode = request.CountryCode.Trim();
|
||||
query = query.Where(p => p.CountryCode == countryCode);
|
||||
}
|
||||
|
||||
return await query
|
||||
.OrderBy(p => p.FirstNameTranscription)
|
||||
.ThenBy(p => p.LastNameTranscription)
|
||||
.Select(p => new IdName<int>
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.FirstName + " " + p.LastName,
|
||||
Description = p.FirstNameTranscription + " " + p.LastNameTranscription
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using AutoMapper;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using Events.WebAPI.Handlers.EF.Models;
|
||||
using Events.WebAPI.Handlers.EF.QueryHandlers.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sieve.Services;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class PeopleQueryHandler : GenericQueryHandler<PersonDTO, Person, int>
|
||||
{
|
||||
public PeopleQueryHandler(EventsContext ctx, ILogger<PeopleQueryHandler> logger, IMapper mapper, ISieveProcessor sieveProcessor)
|
||||
: base(ctx, logger, mapper, sieveProcessor)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using AutoMapper;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using Events.WebAPI.Handlers.EF.Models;
|
||||
using Events.WebAPI.Handlers.EF.QueryHandlers.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sieve.Services;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class RegistrationsQueryHandler : GenericQueryHandler<RegistrationDTO, Registration, int>
|
||||
{
|
||||
public RegistrationsQueryHandler(EventsContext ctx, ILogger<RegistrationsQueryHandler> logger, IMapper mapper, ISieveProcessor sieveProcessor)
|
||||
: base(ctx, logger, mapper, sieveProcessor)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using AutoMapper;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||
using Events.WebAPI.Handlers.EF.Models;
|
||||
using Events.WebAPI.Handlers.EF.QueryHandlers.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sieve.Services;
|
||||
|
||||
namespace Events.WebAPI.Handlers.EF.QueryHandlers;
|
||||
|
||||
public class SportsQueryHandler : GenericQueryHandler<SportDTO, Sport, int>
|
||||
{
|
||||
public SportsQueryHandler(EventsContext ctx, ILogger<SportsQueryHandler> logger, IMapper mapper, ISieveProcessor sieveProcessor)
|
||||
: base(ctx, logger, mapper, sieveProcessor)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user