CQRS - 在 C#、ASP.net Core 中使用 Mediatr 创建 BaseCommandHandler

Dhe*_*mar 1 .net c# design-patterns cqrs mediatr

所以我了解Mediatr了由 Jimmy Bogard 创建的内容,这让我非常惊讶我们如何CQRS使用Mediatr.

我开始在我的应用程序中实现它,然后我意识到我的应用程序中可能有数百个Entities,对于每个实体,我不确定是否创建单独的命令和查询,这与DRY. 所以我开始编写基本命令和处理程序。

public abstract class CreateBaseCommand : IRequest
{    
}

public abstract class DeleteBaseCommand : IRequest
{
}  //... and so on.
Run Code Online (Sandbox Code Playgroud)

和各自的处理程序。

public abstract class CreateBaseHandler : IRequestHandler<CreateBaseCommand>
{
}

public abstract class DeleteBaseCommandHandler : IRequestHandler<DeleteBaseCommand>
{
}//... and so on.
Run Code Online (Sandbox Code Playgroud)

但我意识到,我的域实体仍然需要单独的命令,并且它们必须分别从它们的 Base 命令派生。

然后我想如果我可以将所有命令放在一个并且只有一个基本处理程序。

    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
      }
    }
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更有效的方法来做到这一点,我不太相信使用CommandType和有一种handle方法来执行所有 CRUD 操作的想法。

这是一个好方法还是我应该为每个域实体设置单独的命令集?

Bra*_*rby 6

从技术上讲,您应该为每个创建创建一个单独的命令。添加基础不会给您带来太多好处,并且会使结构复杂化,因此我会摆脱它。

真正的问题是您是从数据模型的角度而不是域模型的角度来考虑这一点的。当您应该为每个商业创意创建一个命令时,您正在为每个表行创建一个命令。

例如,假设您正在编写一个零售系统并为注册用户创建一个新订单,该订单有 5 个订单项。从数据模型的角度来看,您需要为订单发送 1 个创建命令,为行项目发送 5 个创建命令。应该发生的是发送一个命令 AddNewOrderCommand 并让 User 类处理它。User 类方法然后创建新的订单数据库行和所有行项目。您如何添加订单(要创建的行等)现在封装在它所属的方法中,而不是您的命令架构中。

您是否在为您的应用程序使用领域驱动设计?如果没有,您应该考虑它,因为它非常适合复杂系统,并且如果您有数百个实体,则很有可能这是一个复杂系统。在 DDD 的说法中,上面的 User 被称为,Aggregate Root 和 Order 和 Line Item 只是实体。您没有实体的创建命令,只有聚合根。(请注意,一个类有时既可以是聚合根,又可以是另一个聚合根中的普通实体。为什么会发生这种情况以及如何处理它超出了这个问题的范围)

查看您的模型并找到没有意义的东西,除非它们归其他人所有。例如上例中的行项目。在我的数据库中有一个与订单无关的行项目是没有意义的。因此,所有订单项都应由订单创建。拥有一个没有关联用户的订单也是没有意义的。因此,用户应该创建订单。然而,用户似乎是金字塔的顶端,因此它是聚合根并且确实需要创建命令。

如果您分析您的域,您会发现您几乎不需要那么多 Create 命令,因此问题就消失了。