Комментарии 4
Простите, но это капец какой короткий пересказ официальной справки!
На том же fluentvalidation непросто сделать вот что. Как-то понадобилось мне в базе держать данные нескольких пользователей (допустим, заметки) и запрещать показывать чужие. Поэтому даже в самом простом запросе
public class Query : IRequest<NoteDto>
{
public Query(int currentUserId, int noteId)
{
this.CurrentUserId = currentUserId;
this.NoteId = noteId;
}
public int CurrentUserId { get; set; }
public int NoteId { get; }
}
Я либо дважды лезу в базу (на валидаторе в первый раз, на IRequestHandler<Query, NoteDto> — второй), либо отказываюсь от использования валидатора в handler'е и пишу по-старинке, либо пишу громоздкий некрасивый код (потому что надо проверять связку query+полученный из БД результат).
И в общем, это как-то не особо вдохновляет.
Конкретно для вашего случая (если у вас EF например), проще было бы просто условие в фильтре поставить:
var note = _db.Notes.FirstOrDefault(x => x.UserId == currentUserId && x.Id == noteId)
Но вообще это можно решить с помощью RuleSet'ов
Как-то понадобилось мне в базе держать данные нескольких пользователей (допустим, заметки) и запрещать показывать чужие.
А это не задача FluentValidation. Это — задача слоя бизнес логики, в вашем примере — QueryHandler'а, который должен либо самостоятельно определить текущего юзера, либо получить эти данные из Query, а затем либо делегировать выборку репозиторию (читай — sql запросу), либо самостоятельно отфильтровать данные.
FluentValidation — это библиотека исключительно для Presentation Layer и предназначена только для первичной валидации данных, пришедших от пользователя. Например, что email — это email, а не случайная строка, или что возраст — больше нуля, но меньше 120 и, в случае ошибки — детально сообщить об этом юзеру. С чем и справляется блестяще.
Бизнес слою же вообще желательно работать только с ValueObject, которые должны быть реализованы так, чтобы их в принципе было невозможно создать невалидными, но это уже оффтопик.
И, к вашему примеру, добавлю еще, что RequestHandler не должен возвращать DTO. Опять же, потому что RequestHandler — это слой бизнес логики (модели), а DTO — это Presentation Layer. По этому меняем NoteDto на Note (Entity), в контроллер добавляем AutoMapper (или собственный маппер Note -> NoteDto) и радуемся тому что слои не залезают друг в дружку, а код — чистый, красивый и лаконичный.
Спасибо за комментарий. Да, в итоге на похожем и остановился: что для проверок бизнес-правил эта библиотека не подходит.
Единственное, совет насчёт Dto — спорный. Вот тут или вот в этом приложении (оно не совсем чистый DDD, согласен) декларируется другой подход и вполне успешно применяется.
Открытый вебинар «Fluent Validation как инструмент валидации данных»