W
W
WhiteNinja2018-06-19 22:50:58
C++ / C#
WhiteNinja, 2018-06-19 22:50:58

What and how should the Commandhandler return when using the CQRS/CQS principle?

Good afternoon!
Question about using Command-query separation :
Please tell me how best to organize the return of the command execution result from the handler (Not some data, i.e. this is not a Query, but the result of the command execution) ?
If we consider an example (ASP.NET MVC):
There is a ProductController in which there is an Action Create - adding a new product. And after creating a new product, you need to make a Redirect to the page with the details of the newly added product.

public class ProductController : Controller
{

  private readonly ICommandDispatcher _commandDispatcher;
  
  public ProductController(ICommandDispatcher commandDispatcher)
  {
    _commandDispatcher = commandDispatcher;
  }

  [HttpGet]
  public Action Create()
  {
    // ...
    View(createProductCommand);
  }
  
  [HttpPost]
  public Action Create(CreateProductCommand createProductCommand)
  {	
    if(ModelState.IsValid)
    {
      // Как правильно получить ProductId?
      _commandDispatcher.Dispatch(createProductCommand);			
      return RedirectToAction(nameof(Details), new { id = /* ... тут нужно передать ProductId ...*/ });
    }
    
    return View(createProductVm);
  }
}

Command handler example:
public CreateProductHandler : ICommandHandler<CreateProductCommand>
{
  private readonly IUnitOfWorkFactory _uowFactory;
  private readonly IProductRepository _productRepository;
  
  public CreateProductHandler(IUnitOfWorkFactory uowFactory, IProductRepository productRepository) 
  {
    _uowFactory = uowFactory;
    _productRepository = productRepository;
  }
  
  // Возвращает void, а нам нужно когда int, когда string. Т.е. в общем случае TCommandResult
  public void Handle(CreateProductCommand command)
  {
    Product product =  new Product(/* ... create from command ... */);
  
    using(var uow = _uowFactory.Create())
    {
      _productRepository.Insert(product);
      uow.Commit();
    }
  }
}

It turns out that the CommandHandler should actually return some kind of TCommandResult, and not void?
Another example is when deleting multiple products, you need to return the number of products removed as a result of the products command to display the $"{x} products removed" messages.
At the same time, Greg Yang tells everyone that the command handler can just return a list of errors or an exception. (25 minutes).

Answer the question

In order to leave comments, you need to log in

1 answer(s)
G
ggrnd0, 2018-06-20
@ggrnd0

The CommandHandler must return the status of the operation.
In particular, if instead of executing a command, it is queued, the token must be returned.
As a result, we have (to hell with all these Yangs and others) it is impossible to separate Command and Query - the contracts are identical.
But this is only if you are going to implement CQRS in a real application, and not for writing another stupid article about a spherical horse in a vacuum...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question