Skip to content
Charles Solar edited this page Feb 8, 2021 · 9 revisions

Welcome

Thanks for checking out Aggregates.NET - this is a slightly opinionated DDD library meant to help devs connect EventStore and NServiceBus with minimal effort and time. It contains definitions for Entities, and Value Objects which you use in your NServicebus message handlers to process domain commands. It also contains a specifications implementation based off of LinqSpecs to help model your business rules and validate roots and entities.

You can find VERY simple example projects under the "samples" folder here. There is also a TodoMVC-style example here https://github.com/charlessolar/TodoMVC-DDD-CQRS-EventSourcing. For Aggregates.NET specific code check out the domain projects located here.

Using Aggregates.NET

Aggregates.NET is meant to be used in reaction to a domain command in your system. Lets look at a sample handle method from NServiceBus

public async Task Handle(Commands.Create command, IMessageHandlerContext ctx)
{
    var item = await ctx.For<Item>().Get(command.ItemId);
    var serial = await item.For<SerialNumber>().New(command.SerialNumberId);
            
    serial.Create(command.SerialNumber, command.Quantity, command.Effective, command.ItemId);
}

In my example domain, Item is an aggregate root with an entity SerialNumber. Lets go through this line by line:

var item = await ctx.For<Item>().Get(command.ItemId);

This will retrieve the aggregate root Item with id command.ItemId from the event store. In Aggregates.NET you can use Ids of type Guid, String, or long. The only requirement is that the id is unique as each id corresponds to a stream id written to EventStore.

Note

you can mix id types from aggregate to aggregate and even among entities inside 1 aggregate. ctx.For<Item>().Get(Guid.NewGuid()); and ctx.For<Item>().Get("FizzBuzz"); both work

var serial = await item.For<SerialNumber>().New(command.SerialNumberId);

SerialNumber is a child entity of the Item entity. Most would call Item an "Aggregate Root." But unlike other libraries you do need to read the SerialNumber entity from the store as events for this entity are kept in their own stream.

serial.Create(command.SerialNumber, command.Quantity ...;

This is a method call on our entity. Inside the entity, if the call is valid an event will be raised to reflect the changed state of the serial entity.

Need Help?

  • If you have found a bug or need help understanding something please create a issue.