如何在应用命令查询分离 (CQS) 时返回结果

本文关键字:CQS 返回 结果 分离 应用 命令 查询 | 更新日期: 2023-09-27 17:57:24

我在服务端将查询和命令分开,如下所示:

public class ProductCommandService{
    void AddProduct(Product product);
}
public interface ProductQueryService{
    Product GetProduct(Guid id);
    Product[] GetAllProducts();
}

命令查询分离接受方法应更改状态或返回结果。没有问题。

public class ProductController: ApiController{
    private interface ProductCommandService commandService;
    private interface ProductQueryService queryService;
    [HttpPost]
    public ActionResult Create(Product product){
        commandService.AddProduct(product);
        return ???
    }
    [HttpGet]
    public Product GetProduct(Guid id){
        return commandService.GetProduct(id);
    }
    [HttpGet]
    public Product[] GetAllProducts(){
        return queryService.GetAllProducts();
    }
}

我在服务端应用命令查询分离,但不在控制器类中应用。因为用户可能希望看到创建的产品结果。但是命令服务在创建控制器操作 metod 中工作,并且不返回创建的产品。

我们将返回给用户什么?所有产品?CQS 是否适用于应用程序生命周期?

如何在应用命令查询分离 (CQS) 时返回结果

在这种情况下,我通常会在客户端上生成新的实体 ID。喜欢这个:

public class ProductController: Controller{
    private IProductCommandService commandService;
    private IProductQueryService queryService;
    private IIdGenerationService idGenerator;
    [HttpPost]
    public ActionResult Create(Product product){
        var newProductId = idGenerator.NewId();
        product.Id = newProductId;
        commandService.AddProduct(product);
        //TODO: add url parameter or TempData key to show "product created" message if needed    
        return RedirectToAction("GetProduct", new {id = newProductId});
    }
    [HttpGet]
    public ActionResult GetProduct(Guid id){
        return queryService.GetProduct(id);
    }
}

这样,您也遵循了重定向后获取规则,即使不使用 CQRS,也应该这样做。

编辑:抱歉,没有注意到您正在构建 API,而不是 MVC 应用程序。在这种情况下,我将返回新创建的产品的 URL:

public class ProductController: ApiController{
    private IProductCommandService commandService;
    private IProductQueryService queryService;
    private IIdGenerationService idGenerator;
    [HttpPost]
    public ActionResult Create(Product product){
        var newProductId = idGenerator.NewId();
        product.Id = newProductId;
        commandService.AddProduct(product);
        return this.Url.Link("Default", new { Controller = "Product", Action = "GetProduct", id = newProductId });
    }
    [HttpGet]
    public ActionResult GetProduct(Guid id){
        return queryService.GetProduct(id);
    }
}

命令方法不返回任何内容,只更改状态,但命令事件可以返回您需要的参数。

commandService.OnProductAdd += (args)=>{
  var id = args.Product.Id;
}