Так я узнал о Mediatr, созданном Джимми Богардом, и меня действительно поразило, как мы достигаем паттерна CQRS с помощью Mediatr.
Я начал реализовывать это в своем приложении, а затем понял, что в моем приложении могут быть сотни Entities, и для каждой Entity я не уверен в создании отдельных команд и запросов, что было бы полной противоположностью DRY. Итак, я начал писать базовые команды и обработчики.
public abstract class CreateBaseCommand : IRequest
{
}
public abstract class DeleteBaseCommand : IRequest
{
} //... and so on.
И соответствующие обработчики.
public abstract class CreateBaseHandler : IRequestHandler<CreateBaseCommand>
{
}
public abstract class DeleteBaseCommandHandler : IRequestHandler<DeleteBaseCommand>
{
}//... and so on.
Но я понял, что мне все равно понадобятся отдельные команды для объектов моего домена, и они должны будут быть производными от своих базовых команд соответственно.
Тогда я подумал, могу ли я просто объединить все команды в одну и иметь только один базовый обработчик.
public abstract class BaseCommand : IRequest
{
int CommandType
}
public abstract class BaseCommandHandler : IRequestHandler<BaseCommand>
{
public Task<Unit> Handle(BaseCommand request, CancellationToken cancellationToken)
{
if (CommandType == 0)
{
// Create entity
}
if (CommandType == 1)
{
// Update entity
}//.. and so on
}
}
Мне было интересно, есть ли более эффективный способ сделать это, я не очень убежден в идее использования CommandType и у меня есть один метод handle для выполнения всех операций CRUD.
Это хороший подход или мне нужно иметь отдельный набор команд для каждого объекта домена?
@trailmax Итак, вы предлагаете иметь отдельные команды для каждой сущности?
Именно так. Они могут быть очень похожими на *Посмотрите, но позже в каждой сущности будут небольшие отклонения, которые серьезно помешают предлагаемому вами шаблону наследования.





Технически у вас должна быть отдельная команда для каждого творения. Добавление базы ничего не дает и усложняет структуру, поэтому я бы избавился от этого.
Настоящая проблема в том, что вы думаете об этом с точки зрения модели данных, а не модели предметной области. Вы создаете команду для каждой строки таблицы, тогда как вам следует создавать команду для бизнес-идеи.
Например, предположим, что вы пишете систему розничной торговли и создаете новый заказ для зарегистрированного пользователя, и в этом заказе 5 позиций. Глядя на это с точки зрения модели данных, вам нужно отправить 1 команду создания для заказа и 5 команд создания для позиций. Что должно произойти, так это отправить одну команду AddNewOrderCommand и поручить классу User ее обработать. Затем метод класса User создает новую строку базы данных заказов и все позиции. То, как вы добавляете порядок (какие строки создавать и т. д.), Теперь инкапсулируется в методе, которому он принадлежит, а не в вашей командной архитектуре.
Вы используете для своего приложения дизайн, ориентированный на домен? Если нет, вам следует рассмотреть это, потому что он очень хорош для сложных систем, и если у вас есть сотни объектов, шансы хорошие, это квалифицируется как сложная система. На языке DDD указанный выше Пользователь называется, а агрегированный корень, а также заказ и статья являются просто объектами. У вас нет команд создания для сущностей, только для агрегированных корней. (Обратите внимание, что класс иногда может быть как совокупным корнем, так и нормальным объектом в другом совокупном корне. Почему это происходит и как с этим справиться, выходит за рамки этого вопроса)
Просмотрите свою модель и найдите вещи, которые не имеют смысла, если они не принадлежат кому-то другому. Например, позиция из приведенного выше примера. Не имеет смысла иметь в моей базе данных позицию, не связанную с заказом. Следовательно, все позиции должны создаваться по заказам. Наличие заказа без связанного с ним пользователя также не имеет смысла. Следовательно, пользователь должен создать заказ. Однако кажется, что пользователь находится на вершине пирамиды, так что это совокупный корень, и ему нужна команда Create.
Если вы проанализируете свой домен, то обнаружите, что вам не нужно так много команд Create, и проблема исчезнет.
Спасибо, что ответили. Я не получил часть ". У вас нет команд создания для сущностей, только для агрегированных корней". Можете ли вы указать мне какое-нибудь направление здесь?
Для начала вам нужно понять разницу между Aggregate Root и Entity. Гугл то и все станет ясно.
Ах. Я понял, поэтому CreateCommands нужны только для агрегированных корней, а все остальные команды - для других сущностей. Это правильно?
Да, по определению объекты, которые не являются совокупными корнями, принадлежат совокупному корню, и именно этот корень должен создавать объект в ответ на команду «бизнес-идея». Следовательно, вам не нужна команда создания для сущностей.
Спасибо. Это полезно.
@DheerajKumar Этот парень кое-что понял. Полностью согласен с тем, что он сказал здесь, подтверждается моим более чем 5-летним опытом работы с CQRS.
С CQRS вы разделяете вещи. Но затем вы вводите базовую команду, чтобы объединить все это воедино. Это просто плохое применение CQRS. Мы испробовали ваш подход - все закончилось слезами. А команд у нас сотни. Не каждую СУХО стоит внедрять.