2015-06-22 50 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; 
}