I would be interested to hear how other people go about writing and reading aggregate state with Eventstore.
The process we use is:
-
Update our C# Aggregate with the required changes
-
Aggregate creates a list of C# class events
-
C# events gets written to eventstore
-
When we need to rehydrate the aggregate, we retrieve all the json events from Eventstore
-
C# then deserialise back to each C# event class and applies to the Aggregate
There are two things that trouble me with the approach:
- We have to return all the events (outwith snapshots), and these events tend to have duplicate fields (customer indentifiers etc)
For example:
{ “organisationId” : 1, “lineTotal” : 1.45 }
{ “organisationId” : 1, “lineTotal” : 0.99 }
``
- When we write the events, we have to include “optional” fields.
By this, if we have a C# event that has a field only uses in certain scenarios, the field would always be written out in json (with the default value)
For example:
{
“ageCheck” : false
}
``
This field (in our system we almost always be false, so it seems a waste to always write this (but, it really does need to be part of the event when it’s true, rather than a new event)
So, how does this sound:
Our Aggregate can use annoymous types for creating the events:
public void AddSaleLine(Decimal lineTotal)
{
//Only include what we want
var saleLine = new {
type = “saleLine” // no assembly type needed
lineTotal
}
var @event = JsonConvert.Serialise(saleLine);
}
``
public void AddSaleLineWithAgeCheck(Decimal lineTotal)
{
//Only include what we want
var saleLine = new {
type = “saleLine” // no assembly type needed
lineTotal,
ageCheck = true
}
var @event = JsonConvert.Serialise(saleLine);
}
``
When we need to rehdyrate our Aggregate, rather than bringing back all the events, we simply return the state (and deserialise it to our aggregate)
The state could be maintained either by:
-
Transient query
-
Partition
The state would hold the version number in for concurrency for future writes.
Steven