Super-short example So how does it actually look when writing an application with Revo?
These few following paragraphs show how could one design super-simple application that can save tasks using event-sourced aggregates and then query them back from a RDBMS.
A little-bit more complete application based on this code, along with some walkthrough, can be found in the Task list app example .
Event
The event that happens when changing a task's name.
Copy public class TodoRenamedEvent : DomainAggregateEvent
{
public TodoRenamedEvent ( string name)
{
Name = name;
}
public string Name { get ; }
}
Aggregate
The task aggregate root.
Copy public class Todo : EventSourcedAggregateRoot
{
public Todo ( Guid id , string name) : base(id)
{
Rename (name);
}
protectedTodo ( Guid id) : base(id)
{
}
public string Name { get ; private set ; }
public void Rename ( string name)
{
if ( ! Name != name)
{
Publish ( new TodoRenamedEvent (name));
}
}
private void Apply ( TodoRenamedEvent ev)
{
Name = ev . Name ;
}
}
Command and command handler
Command to save a new task.
Copy public class CreateTodoCommand : ICommand
{
public CreateTodoCommand ( string name)
{
Name = name;
}
[ Required ]
public string Name { get ; }
}
Copy public class TodoCommandHandler : ICommandHandler < CreateTodoCommand >
{
private readonly IRepository repository;
public TodoCommandHandler ( IRepository repository)
{
this . repository = repository;
}
public Task HandleAsync ( CreateTodoCommand command , CancellationToken cancellationToken)
{
var todo = new Todo ( command . Id );
todo . Rename ( command . Name );
repository . Add (todoList);
return Task . CompletedTask ;
}
}
Read model and projection
Read model and a projection for the event-sourced aggregate.
Copy public class TodoReadModel : EntityReadModel
{
public string Name { get ; set ; }
}
Copy public class TodoListReadModelProjector : EFCoreEntityEventToPocoProjector < Todo , TodoReadModel >
{
public TodoListReadModelProjector ( IEFCoreCrudRepository repository) : base(repository)
{
}
private void Apply ( IEventMessage < TodoRenamedEvent > ev)
{
Target . Name = ev . Event . Name ;
}
}
Query and query handler
Query to read the tasks back from a RDBMS.
Copy public class GetTodosQuery : IQuery < IQueryable < TodoReadModel >>
{
}
Copy public class TaskQueryHandler : IQueryHandler < GetTodoQuery , IQueryable < TodoReadModel >>
{
private readonly IReadRepository readRepository;
public TaskListQueryHandler ( IReadRepository readRepository)
{
this . readRepository = readRepository;
}
public Task < IQueryable < TodoReadModel >> HandleAsync ( GetTodoListsQuery query , CancellationToken cancellationToken)
{
return Task . FromResult (readRepository
. FindAll < TodoListReadModel >());
}
}
ASP.NET Core controller
Or just any arbitrary endpoint from where to send the command and queries from. :)
Copy [ Route ( "todos" )]
public class TodoController : CommandApiController
{
[ HttpGet ( "" )]
public Task < IQueryable < TodoReadModel >> Get ()
{
return CommandBus . SendAsync ( new GetTodosQuery ());
}
[ HttpPost ( "" )]
public Task Post ([ FromBody ] CreateTodoDto payload)
{
return CommandBus . SendAsync ( new CreateTodoCommand ( payload . Name ));
}
public class CreateTodoDto
{
public string Name { get ; set ; }
}
}
Finish!
Now you are ready save the TO-DOs to an event store and read them from regular RDBMS read models.