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

C# 如何在应用命令查询分离(CQS)时返回结果,c#,design-patterns,command-query-separation,C#,Design Patterns,Command Query Separation,我在服务端分离查询和命令,如下所示: public class ProductCommandService{ void AddProduct(Product product); } public interface ProductQueryService{ Product GetProduct(Guid id); Product[] GetAllProducts(); } 接受方法应更改状态或返回结果。没问题 public class ProductControlle

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

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();
    }
}
我正在服务端应用命令-查询分离,但在控制器类中没有应用。因为用户可能希望看到创建的产品结果。但是,命令服务创建控制器操作方法中工作,并且不返回创建的产品


我们将向用户返回什么?所有产品?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);
    }
}
这样,即使不使用CQR,您也应该遵循POST-REDIRECT-GET规则

编辑: 抱歉,没有注意到您正在构建的是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;
}

看起来有道理,您正在手动生成对象ID。这可能导致数据库上的ID重复。可能有数十亿条记录。如何解决?当然,必须有一个DB唯一约束来防止数据不一致。Id生成器必须保证Id的唯一性(例如,必须是线程安全的)。有了guid,你就可以从盒子里拿出来。将整数作为ID很难做到,但仍然是可能的(例如,使用一个全局标识计数器,可以是一个具有一个标识字段的简单SQL表)。您的意思是:如果您选择ID类型作为GUID,则不可能复制。从技术上讲,不是“不可能”,而是。请注意术语QCS不是CQRS。无论如何,请看这篇博文: