Skip to content

Transactions

Kieron Lanning edited this page Apr 16, 2026 · 1 revision

Transactions

Why transactions exist here

Many application workflows need to save multiple aggregates together:

  • creating an order and reserving inventory
  • checking out a cart across many inventory records
  • transferring stock between locations

The framework exposes IEventStoreTransactionFactory and IEventStoreTransaction for those scenarios.

Basic usage

await using var transaction = transactionFactory.Create();
transaction.Enlist(order, store);
transaction.Enlist(inventory, store);

var result = await transaction.CommitAsync(cancellationToken);
if (!result.Success)
{
    // inspect result.Results
}

Coordination model

EventStoreTransaction chooses the strongest available coordination mode automatically:

  1. Native transaction mode when all enlisted stores share the same provider-native transaction boundary.
  2. Logical shared-correlation mode when native coordination is unavailable or the enlisted stores do not share the same boundary.

Important behavior

  • The transaction carries a shared CorrelationId.
  • The first failure stops further processing.
  • In logical fallback mode, already persisted aggregates are not rolled back.
  • TransactionResult reports per-aggregate outcomes so callers can see what saved, skipped, or failed.

Sample workflows

The sample application uses transactions in the places where they matter most:

Workflow Aggregates
Checkout OrderAggregate + one or more InventoryAggregate instances
Order fulfilment OrderAggregate + InventoryAggregate
Stock transfer source InventoryAggregate + destination InventoryAggregate

Facade-friendly usage

The sample shows transaction usage with the non-generic facades:

transaction.Enlist(order, store);
transaction.Enlist(inventory, store);

That is the recommended knowledge-base example because it matches the application-facing usability goal of the framework.

Clone this wiki locally