DDD、CQRS 和 Mediatr 查询过滤

DDD, CQRS and Mediatr query filtering

我正在做一个遵循 CQRS 和 Mediatr 模式的项目。

我有一个这样设置的实体

    public class Order
{
    public Guid OrderId { get; set; }

    public Guid CreatedByUserId { get; set; }

    public Guid? AcceptedByUserId { get; set; }

    public string Registration { get; set; }

    public string Description { get; set; }

    public User CreatedByUser { get; set; }
    public User AcceptedByUser { get; set; }
}

当我编写我的 2 个查询 GetAllOrdersCreatedByUser 和 GetAllOrdersAcceptedByUser 时,所有代码实际上是相同的。

唯一的例外是我在 CreatedByUserId 上的已创建查询和我在 AcceptedByUserId 上的已接受查询

GetAllOrdersAcceptedByUser :-

        public async Task<OrderAcceptedByUserListViewModel> Handle(GetAllOrdersAcceptedByUserQuery request, CancellationToken cancellationToken)
    {
        var model = new OrderAcceptedByUserListViewModel
        {
            Orders = await _context.Order
            .Where(x => x.AcceptedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)
        };

        return model;
    }

GetAllOrdersCreatedByUser:-

        public async Task<OrderCreatedByUserListViewModel> Handle(GetAllOrdersCreatedByUserQuery request, CancellationToken cancellationToken)
    {
        var model = new OrderCreatedByUserListViewModel
        {
            Orders = await _context.Order
            .Where(x => x.CreatedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)
        };

        return model;
    }

这是正确的实现方式,还是根据从控制器调用它的方式,让 1 个查询同时执行这两种操作在客观上更好?

编辑:添加了更好的标签

查询可以保持独立(因此它们遵循 SOLID)并且您可以通过其他方式避免代码重复。也许尝试提取查询的重复部分以获取订单,而不是首先在 virtual 方法中使用 where 过滤它们,然后在各自的查询中过滤它们。

首先,合并classes GetAllOrdersCreatedByUserQueryGetAllOrdersAcceptedByUserQuery

参考以下class:

public class GetAllOrdersByUserQuery :  : IRequest<OrdeListViewModel>
{
    // if OrderAcceptedByUser is true else OrderCreatedByUser = false
    public bool AcceptedOrCreatedBit { get; set; } 
    public string UserId { get; set; }
}

并查看 OrderCreatedByUserListViewModel and OrderCreatedByUserListViewModel

的模型

参考以下视图模型:

public class OrdeListViewModel
{
    public List<Order> Orders { get; set; }
}

最后你的 MediatR 句柄方法应该是这样的:

public async Task<OrdeListViewModel> Handle(GetAllOrdersByUserQuery request, CancellationToken cancellationToken)
{
    OrdeListViewModel model = new OrdeListViewModel();
    if (request.AcceptedOrCreatedBit) // true for OrderAcceptedByUser
    {

            model.Orders = await _context.Order
            .Where(x => x.AcceptedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)

    }
    else // false for OrderCreatedByUser
    {

            model.Orders = await _context.Order
            .Where(x => x.CreatedByUserId == request.UserId)
            .Select(OrderDto.Projection)
            .OrderBy(o => o.Registration)
            .ToListAsync(cancellationToken)

    }

    return model;
}

您可以将规范模式应用于查询,即一个以谓词作为参数的查询。

但是 DDD 提倡使用一种无​​处不在的语言,如果你的用户不使用谓词说话,而是使用具体的方法名称,我会向用户提供 2 个查询,然后如果你不想重复代码,两个查询都将使用谓词调用通用查询。