2015-06-22 81 views
1

我在服务端分开我的查询和命令如下:如何返回结果,而将命令查询分离(CQS)

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

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

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

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

我申请上的服务侧命令查询分离,但在控制器类不应用。因为用户可能想要查看创建的产品结果。但commandService中创建控制器操作metod并不返回创建的产品。

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

+1

小心你的术语QCS不是CQRS。无论如何,看到这篇博客文章:http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/ –

回答

1

在这种情况下,我通常会在客户端上生成新的实体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应用程序。 在这种情况下,我会返回一个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); 
    } 
} 
+0

看起来有道理,你手动生成你的对象ID。这可能是数据库上的身份证复制。可能是数十亿记录。你如何解决它? – barteloma

+0

必须有一个数据库唯一约束来防止数据不一致。 Id生成器必须保证Id唯一性(例如,必须是线程安全的)。使用GUID您可以获得这个开箱即用的功能。使用整数作为ID很难做到,但仍然可能(例如使用一个全局标识计数器,可能是一个带有一个标识字段的简单SQL表)。 –

+0

您的意思是:如果您选择ID类型作为GUID,则重复是不可能的。 – barteloma

1

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

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