Столкнулся с вот какой проблемой переделывая репозиторий на CQS.
Был метод выбирающий из базы контакты по предикату и сортирующий по определённому полю:
public async Task<IEnumerable<Contact>> GetAsync(Expression<Func<Contact, bool>> predicate, Expression<Func<Contact, TOrderKey>> orderBy, CancellationToken cancellationToken)
{
return await this.ApplicationDbContext.Contacts
.Include(x => x.ApplicationUser.City)
.Where(predicate)
.OrderBy(orderBy)
.AsNoTracking()
.ToArrayAsync(cancellationToken);
}
Работает, всё окей. Стал переносить в Mediatr - понял, что не понимаю, как мне написать обобщённый запрос (никогда не делал) и что-то не нахожу примеров.
Я так понимаю, что должно быть как-то так:
Запрос:
public class Query<TOrderKey> : IRequest<IEnumerable<Contact>>
where TOrderKey : class
{
public Query(Expression<Func<Contact, bool>> predicate, Expression<Func<Contact, TOrderKey>> orderBy)
{
this.Predicate = predicate;
this.OrderBy = orderBy;
}
public Expression<Func<Contact, bool>> Predicate { get; }
public Expression<Func<Contact, TOrderKey>> OrderBy { get; }
}
Обработчик:
public class Handler<TOrderKey> : BaseHandler, IRequestHandler<Query<TOrderKey>, IEnumerable<Contact>>
where TOrderKey : class
{
public Handler(ApplicationDbContext applicationDbContext)
: base(applicationDbContext)
{
}
public async Task<IEnumerable<Contact>> Handle(Query<TOrderKey> request, CancellationToken cancellationToken)
{
return await this.ApplicationDbContext.Contacts
.Include(x => x.ApplicationUser.City)
.Where(request.Predicate)
.OrderBy(request.OrderBy)
.AsNoTracking()
.ToArrayAsync(cancellationToken);
}
}
И оно даже компилируется... но падает в рантайме при попытке вызова с ошибкой:
Expression<Func<Contact, bool>> expr = x => x.OwnerId == request.UserID;
if (request.Filter.CityId != null)
{
Expression<Func<Contact, bool>> exprCity = x => x.ApplicationUser.CityId == request.Filter.CityId;
expr = expr.AndAlso(exprCity);
}
if (!string.IsNullOrWhiteSpace(request.Filter.SearchText))
{
Expression<Func<Contact, bool>> exprText = x => x.DisplayName.Contains(request.Filter.SearchText) || x.Notes.Contains(request.Filter.SearchText);
expr = expr.AndAlso(exprText);
}
return this.Mediator.Send(new Contacts.List.Query<string>(expr, x => x.DisplayName));
An unhandled exception occurred while processing the request.
InvalidOperationException: Handler was not found for request of type
MediatR.IRequestHandler2[Application.Contacts.List.Query
1[System.String],System.Collections.Generic.IEnumerable`1[Domain.Models.Contact]].
Register your handlers with the container. See the samples in GitHub
for examples.
MediatR.Internal.RequestHandlerBase.GetHandler(ServiceFactory factory)
Регистрация mediatr в Startup.cs самая обычная, все остальные обработчики находятся без проблем:
services.AddMediatR(typeof(Application.City.Create.Command).GetTypeInfo().Assembly);
Здесь указывается, что для того, чтобы generic handler работали - нужно в первую очередь, чтобы применённый в проекте DI контейнер поддерживал динамическую диспетчеризацию (polymorphic dispatch). У меня используется рекомендованный для .net core MediatR.Extensions.Microsoft.DependencyInjection и у него такая поддержка заявлена (см. на заглавной репозитория: "Supports generic variance of handlers.")
Однако у меня обобщённый не только handler, но и query.
Как правильно делать подобные запросы в mediatr?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Встала задача сделать выборку нескольких Count-значений из 2-ух таблиц базы данныхРешил сделать это с помощью лямбда-выражений
Извиняюсь за такой тупой вопрос, но я просто разбит, что не могу понятьПрограмма работает так, сначала запускается форма с логотипом, а потом...
Возможно ли в функции Replace в качестве одно из аргумента использовать регулярное выражение? Если да, то какой синтаксис?