Guid of created aggregate root in CQRS

844 views Asked by At

Looking at this code from here:

[Serializable]
public class CreateClientCommand : Command
{
    public string ClientName { get; private set; }
    public string Street { get; private set; }
    public string StreetNumber { get; private set; }
    public string PostalCode { get; private set; }
    public string City { get; private set; }
    public string PhoneNumber { get; private set; }

    public CreateClientCommand(Guid id, string clientName, string street, string streetNumber, string postalCode, string city, string phoneNumber) : base(id)
    {
        ClientName = clientName;
        Street = street;
        StreetNumber = streetNumber;
        PostalCode = postalCode;
        City = city;
        PhoneNumber = phoneNumber;
    }
}

The Guid here is just relevant for the command. It is not the Guid of the (potentially) created aggregate root. What is the best practice to obtain this Guid and how are any potential validation errors communicated back to the the code that puts a command on the bus? For example like this:

_bus.Publish(new CreateClientCommand(
     Guid.NewGuid(),
     _clientDetailsReport.ClientName,
     _clientDetailsReport.Street,
     _clientDetailsReport.StreetNumber,
     _clientDetailsReport.PostalCode,
     _clientDetailsReport.City,
     _clientDetailsView.PhoneNumber));

_bus.Commit();   

I understand that CQRS usually implements eventual consistency. This means that it might take a while before the client is actually created. Some MVC/CQRS code uses this approach:

[HttpPost]
public ActionResult Add(DiaryItemDto item)
{
    ServiceLocator.CommandBus.Send(new CreateItemCommand(Guid.NewGuid(),item.Title,item.Description,-1,item.From,item.To));

    return RedirectToAction("Index");
}

Obviously, the index page might show some grid containing the DiaryItems and the user might be able to see the latest created DiaryItem (potentiality after a while). Any feedback would be very much appreciated. Thanks.

3

There are 3 answers

5
Sebastian Good On BEST ANSWER

Are you asking about the distinction between an ID for the command itself, versus the ID of the entity it might create? The former would typically be an infrastructure concern, found on something like a message envelope, buried in a RPC protocol, or the like. The latter would be part of your domain. (Though in many cases, it's nice to treat the ID of an entity as an infrastructure concern as well, since you might choose it for convenience in your persistence model.)

1
SammoSampson On

The easiest way to do this is to use the guid that you pass on the command as the actual aggregate Id and then you have it to hand and don't have to wait for it to be communicated back down on an event

0
user1496062 On

Not sure why your command has an id it confuses things ( Yes some distributed systems use this but it should be a last resort). Most developers would see this as the id of the aggregate .

Generally just create the aggregate Id and send it with the command . After all the command is creating the Entity ..

Commands should in most cases be sync so you can throw errors back . With async commands you really should have a call back for success or failure ( and async should only be used where you really have the need it adds a lot of cost to the system ) .

You don't move to the next step ( if you need a next step ) until either A) Its a system that deals with eventual consistency, a lot of business logic does do this. eg waiting for the exchange or a 3rd party to process something , then the work is waiting for that information . ( Ie the command creates an Order but the processing of the order eg OrderDetail may not be there yet and the order has a state of Order Processing) B) You have success , timeout or failure response to command before continuing .