I'm building a web application with C#, and I have an aggregate root which has several entities and value objects. Then I have a repository object which persists the aggregate to the database (I'm using ADO.NET as my infrastructure persistence layer).
The aggregate also has several events attached to its methods, so that other actions can be taken outside the aggregate (for example, the method OpenRequisition of a Customer aggregate fires the event RequisitionCreatedEvent, and a handler then queues an action to update statistics regarding the customer.
This is a simplified sample.
class Customer {
private Guid _id;
private string _shortName;
private string _legalName;
private TaxCode _taxCode;
private ContactInfo _primaryContact;
private List<Requisitions> _requisitions; //Requisition is an entity
private IDomainEvents _events;
// and so many other fields
public Requisition OpenRequisition(RequisitionDefinition definition, User requestedBy)
{
Requisition req = ... // create the new requisition somehow
_requisitions.Add(req);
_events.Invoke(new RequisitionCreatedEvent(this, req));
return req;
}
// and so on
}
The problem I'm facing is not with how to persist, but how to reconstruct the aggregate object from the database. Many of the customer's fields have setters, such as the ShortName or LegalName, or even TaxCode. Others does not, such as the _requisitions field. I have no direct way of reconstructing existing requisitions. If I expose _requisitions somehow (as an List property), then I could simple do something like this in my repository:
var requisitions = ... // get requisitions for this customer
var customer = new Customer(id);
customer.Requisitions.AddRange(requisitions);
But then elsewhere one could do:
customer.Requisitions.Add(new Requisition());
bypassing the logic and validations set in OpenRequisition method. On the other hand, if I invoke OpenRequisition method from my repository, then the event handler will get called each time, and it shouldn't, because I'm reconstructing the object from the database, not actually opening a new requisition.
What I have so far, is to create a constructor and then pass all these parameters in there, something like this:
public Customer(IDomainEvents events, Guid id, IEnumerable<Requisition> requisitions, ... and so on)
{
... // perform validations
_events = events;
_id = id;
_requisitions = new List<Requisition>(requisitions);
... // and so on
}
However, this aggregate has several other children nodes, and so the constructor is growing and growing, and it doesn't feel right. At one point I tried to create factory class, but I still need the large constructor, or something like having internal setters even for _events and _requisitions, and it still doesn't seem right.
Hence, my question is: how to reconstruct complex aggregate roots, how to pass all the parameters the aggregate needs to keep functioning without having the object to perform already made work (such as firing the event handler). Otherwise, what options would you consider on scenarios such as this?
Factory
class which sets theinternal
properties of your aggregate seems fine to me.