DDD,CQRS和Mediatr查询过滤

时间:2018-11-29 23:09:24

标签: c# domain-driven-design dbcontext cqrs mediatr

我正在按照CQRS和Mediatr模式进行项目。

我有一个这样设置的实体

MSC000001: Failed to start service jboss.web.deployment.default-host
Start Exception in service jboss.web.development.default-host./

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

唯一的例外是在Created查询中,我的位置在CreatedByUserId上,而我的Accepted查询中的位置在AcceptedByUserId上

GetAllOrdersAcceptedByUser:-

    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; }
}

GetAllOrdersCreatedByUser:-

        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;
    }

这是正确的实现,还是客观上更好的是让1个查询可以同时执行两个查询,这取决于从控制器调用它的方式?

编辑:添加了更好的标签

3 个答案:

答案 0 :(得分:1)

查询可以保持分开(因此它们遵循SOLID),并且您可以通过其他某种方式避免代码重复。也许尝试提取查询的重复部分以获取订单,而无需先在where方法中使用virtual对其进行过滤,然后再在相应的查询中对其进行过滤。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

首先,合并类GetAllOrdersCreatedByUserQueryGetAllOrdersAcceptedByUserQuery

请参阅以下类以供参考:

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;
}