【问题标题】:DDD, CQRS and Mediatr query filteringDDD、CQRS 和 Mediatr 查询过滤
【发布时间】:2018-11-29 23:09:24
【问题描述】:

我正在从事一个遵循 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 时,所有代码实际上是相同的。

唯一的例外是在 Created 查询中我的 where 在 CreatedByUserId 上,而我 Accepted 的查询在 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 个查询,这取决于从控制器调用的方式?

编辑:添加了更好的标签

【问题讨论】:

  • 围绕这些方法的类是什么?

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      首先,合并类GetAllOrdersCreatedByUserQuery和GetAllOrdersAcceptedByUserQuery

      请参阅以下课程以供参考:

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

      【讨论】:

        猜你喜欢
        • 2014-10-21
        • 2019-05-09
        • 2019-03-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-03
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多