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

How to return result while applying Command query separation (CQS)

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

public class ProductCommandService{
    void AddProduct(Product product);
}

public interface ProductQueryService{
    Product GetProduct(Guid id);
    Product[] GetAllProducts();
}

Command Query Separation 接受方法应该改变状态或 return 结果。没问题。

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

我在服务端应用命令查询分离,但在控制器class中没有应用。因为用户可能希望看到创建的产品结果。但是 commandServiceCreate Controller Action 方法中工作,而不是 return 创建产品。

我们会return给用户什么?所有产品? 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);
    }
}

这样您也遵循了 POST-REDIRECT-GET 规则,即使不使用 CQRS 也应该这样做。

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

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

命令方法不return任何东西,只改变状态但命令事件可以return你需要的参数。

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