Storing Events and Preconditions¶
Writing to the event store is a single, atomic operation: you hand EventSourcingKit one or more event candidates and, optionally, a set of preconditions that must hold for the write to be accepted. If any precondition fails, nothing is written.
Event Candidates and Subjects¶
You never store a bare event. Instead, you wrap it in an EventCandidate, which pairs the event data with a Subject:
var subject = new Subject($"/books/{bookId}");
var candidate = new EventCandidate(
subject,
new BookRegistered(bookId, title, author)
);
A subject is a hierarchical path that identifies the entity an event belongs to, and it always starts with a slash, for example /books/42. You do not supply the event's type name or source: EventSourcingKit derives the type from the [EventType] attribute and the source from your configuration.
If you configure a SubjectPrefix, it is prepended to every subject automatically, on both writing and reading, which lets several applications share one store without colliding.
Storing One or Many Events¶
Use StoreEvent for a single event and StoreEvents for several. Storing several at once is atomic: they are written together or not at all.
await eventStore.StoreEvents(
[firstCandidate, secondCandidate],
[new IsSubjectPristinePrecondition(subject)],
cancellationToken
);
Both methods return the stored events, now carrying their assigned Id, Time, and other metadata.
Preconditions¶
Preconditions are how you enforce consistency at the moment of writing. EventSourcingKit offers four:
IsSubjectPristinePrecondition– the write succeeds only if no event has ever been stored under the subject. Use it to create an entity exactly once.IsSubjectPopulatedPrecondition– the write succeeds only if the subject already has events. Use it when an entity must already exist.IsSubjectOnEventIdPrecondition– the write succeeds only if the subject's latest event has the givenId. This is optimistic concurrency: you read state up to a known event, then write on the condition that nothing has changed since.IsEventQlQueryTruePrecondition– the write succeeds only if the given EventQL query evaluates to true, for arbitrary, query-based invariants.
Because preconditions are checked by the store itself, they hold even when several writers act at the same time.
For More Information¶
- Storing and Reading Events is the introductory walkthrough.
- State and Reducers shows how to load an entity's state before deciding what to write.
- Configuration documents the
SubjectPrefixoption.