2015-06-22 6 views
1

Я отделяя мой запрос и команду на стороне службы, как это:Как вернуть результат, применяя разделение команд запроса (ОКК)

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 работает в Создать Контроллер Действие метод и не возвращает созданный продукт.

Что мы будем возвращать пользователю? Все продукты? Будет ли CQS использовать жизненный цикл приложения?

+1

Будьте осторожны с вашей терминологией. QCS не является CQRS. Во всяком случае, см. Это сообщение в блоге: http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/ –

ответ

1

В таком случае я обычно запускаю создание новых идентификаторов объектов на клиенте. Как это:

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.

EDITED: Извините, не заметил, что вы создаете 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

Похоже, что вы имеете смысл, вы генерируете свой идентификатор объекта вручную. Это возможно дублирование идентификатора в базе данных. Может быть миллиарды записей. Как вы его решаете? – barteloma

+0

Для предотвращения несогласованности данных, конечно, должно быть уникальное ограничение БД. Генератор Id, в свою очередь, должен гарантировать уникальность идентификатора (например, должен быть потокобезопасным). С GUID вы получаете это из коробки. Труднее делать с целыми как идентификаторы, но все же возможно (например, использовать один глобальный счетчик идентичности, может быть простой таблицей SQL с одним полем идентификации). –

+0

Вы имеете в виду: Если вы выберете идентификатор типа GUID, дублирование невозможно. – barteloma

1

метода Команда не возвращает ничего, только изменяет состояние, но командные события могут вернуть аргументы, которые вам нужны.

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