Sto lavorando a un'implementazione CQRS event-sourced, utilizzando DDD nel livello applicazione/dominio. Ho un modello a oggetti che assomiglia a questo:Una root aggregata event-source può accedere al repository di sourcing degli eventi?
public class Person : AggregateRootBase
{
private Guid? _bookingId;
public Person(Identification identification)
{
Apply(new PersonCreatedEvent(identification));
}
public Booking CreateBooking() {
// Enforce Person invariants
var booking = new Booking();
Apply(new PersonBookedEvent(booking.Id));
return booking;
}
public void Release() {
// Enforce Person invariants
// Should we load the booking here from the aggregate repository?
// We need to ensure that booking is released as well.
var booking = BookingRepository.Load(_bookingId);
booking.Release();
Apply(new PersonReleasedEvent(_bookingId));
}
[EventHandler]
public void Handle(PersonBookedEvent @event) { _bookingId = @event.BookingId; }
[EventHandler]
public void Handle(PersonReleasedEvent @event) { _bookingId = null; }
}
public class Booking : AggregateRootBase
{
private DateTime _bookingDate;
private DateTime? _releaseDate;
public Booking()
{
//Enforce invariants
Apply(new BookingCreatedEvent());
}
public void Release()
{
//Enforce invariants
Apply(new BookingReleasedEvent());
}
[EventHandler]
public void Handle(BookingCreatedEvent @event) { _bookingDate = SystemTime.Now(); }
[EventHandler]
public void Handle(BookingReleasedEvent @event) { _releaseDate = SystemTime.Now(); }
// Some other business activities unrelated to a person
}
Con la mia comprensione delle DDD finora, sia persona e prenotazioni sono separate radici di aggregazione per due motivi:
- Ci sono momenti in cui i componenti d'affari estrarre gli oggetti di prenotazione separatamente dal database. (ad esempio, una persona che è stata rilasciata ha modificato una prenotazione precedente a causa di informazioni errate).
- Non ci devono essere conflitti di blocco tra Persona e Prenotazione ogni volta che è necessario aggiornare una prenotazione.
Un altro requisito aziendale è che una prenotazione non può mai verificarsi per una persona più di una volta alla volta. A causa di ciò, sono preoccupato di interrogare il database di query sul lato di lettura in quanto potrebbe esserci qualche incongruenza (a causa dell'uso di CQRS e di un database di lettura eventualmente coerente).
Nel caso in cui le radici aggregate possano interrogare il backing store basato su evento con id per gli oggetti (caricandoli lentamente se necessario)? Ci sono altre vie di implementazione che avrebbero più senso?
"persona pubblica (identificazione Identification) { Applicare (nuova PersonCreatedEvent (identificazione));} " cosa succede se si sta costruendo l'oggetto dalla memoria, non si sta creando una nuova persona, ma vi sarà la pubblicazione un nuovo evento. Mi piace il modo in cui definisci i gestori di eventi.Quindi, sapendo che lo stato di un oggetto può essere modificato solo quando si applica un comando a un repository, forse dovresti aggiungere anche i gestori di comandi, a meno che non si stia realizzando un evento completo, che IMHO non ha molto senso. – Marco
Quello che non riesco a capire è perché stai gestendo un evento che il tuo repository dovrebbe pubblicare? "BookingCreatedEvent" – Marco