Event Store Schema Objects
Overriding the Schema
By default, the event store database objects are created in the default schema for the active IDocumentStore
. If you wish, you can segregate the event store objects into a separate schema with this syntax:
var store = DocumentStore.For(_ =>
{
_.Connection("some connection string");
// Places all the Event Store schema objects
// into the "events" schema
_.Events.DatabaseSchemaName = "events";
});
Configuration
If Marten is being used in a distributed scenario, where multiple process can be appending events to the same stream at the same time, you should set UseAppendEventForUpdateLock
to true
on the StoreOptions
Events
(EventGraph) configuration. This will add a FOR UPDATE
lock to the mt_append_event
function that will ensure that the same stream cannot have its version
updated by multiple processes at the same time, which could lead to a pk_mt_events_stream_and_version
constraint violation from the mt_events
and mt_streams
versions getting out of sync.
Database Tables
The events are stored in the mt_events
table, with these columns:
seq_id
- A sequential identifier that acts as the primary keyid
- A Guid value uniquely identifying the event across databasesstream_id
- A foreign key to the event stream that contains the eventversion
- A numerical version of the event's position within its event streamdata
- The actual event data stored as JSONBtype
- A string identifier for the event type that's derived from the event type name. For example, events of typeIssueResolved
would be identified as "issue_resolved." Thetype
column exists so that Marten can be effectively used without the underlying JSON serializer having to embed type metadata.timestamp
- A database timestamp written by the database when events are committed.tenant_id
- Identifies the tenancy of the eventmt_dotnet_type
- The full name of the underlying event type, including assembly name, e.g. "Marten.Testing.Events.IssueResolved, Marten.Testing"
The "Async Daemon" projection supports keys off of the sequential id, but we retained the Guid id field for backward compatibility and to retain a potential way to uniquely identify events across databases.
In addition, there are a couple other metadata tables you'll see in your schema:
mt_streams
- Metadata about each event streammt_event_progression
- A durable record about the progress of each async projection through the event store
And finally, a couple functions that Marten uses internally:
mt_append_event
- Writes event data to themt_events
andmt_streams
tablesmt_mark_event_progression
- Updates themt_event_progression
table
Event Metadata in Code
Hopefully, it's relatively clear how the fields in mt_events
map to the IEvent
interface in Marten:
/// <summary>
/// A reference to the stream that contains
/// this event
/// </summary>
public Guid StreamId { get; set; }
/// <summary>
/// A reference to the stream if the stream
/// identifier mode is AsString
/// </summary>
public string? StreamKey { get; set; }
/// <summary>
/// An alternative Guid identifier to identify
/// events across databases
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// An event's version position within its event stream
/// </summary>
public long Version { get; set; }
/// <summary>
/// A global sequential number identifying the Event
/// </summary>
public long Sequence { get; set; }
/// <summary>
/// The UTC time that this event was originally captured
/// </summary>
public DateTimeOffset Timestamp { get; set; }
public string TenantId { get; set; } = Tenancy.DefaultTenantId;
/// <summary>
/// Optional metadata describing the causation id
/// </summary>
public string? CausationId { get; set; }
/// <summary>
/// Optional metadata describing the correlation id
/// </summary>
public string? CorrelationId { get; set; }
/// <summary>
/// This is meant to be lazy created, and can be null
/// </summary>
public Dictionary<string, object>? Headers { get; set; }
The full event data is available on EventStream
and IEvent
objects immediately after committing a transaction that involves event capture. See diagnostics and instrumentation for more information on capturing event data in the instrumentation hooks.