Oracle Provider
The Oracle provider brings Excalibur's reliable-persistence subsystems to Oracle Database. It offers Dapper-based event sourcing, outbox, inbox, and saga stores over the managed Oracle.ManagedDataAccess.Core driver — behind the same store abstractions used by every other provider, so your application code is unchanged.
The Oracle packages are opt-in: install only the subsystems you use, and register each with its AddOracle* / UseOracle extension.
Before You Start
- .NET 10.0
- An Oracle Database instance (local, cloud, or Autonomous Database)
- Familiarity with event sourcing, the outbox pattern, the inbox pattern, and sagas
Packages
| Package | Registers | Subsystem |
|---|---|---|
Excalibur.EventSourcing.Oracle | IEventStore, ISnapshotStore | Event sourcing |
Excalibur.Outbox.Oracle | Oracle outbox store | Outbox pattern |
Excalibur.Inbox.Oracle | IInboxStore | Inbox pattern |
Excalibur.Saga.Oracle | ISagaStore, saga timeout store | Sagas |
Common dependencies: Oracle.ManagedDataAccess.Core, Dapper
Event Sourcing
dotnet add package Excalibur.EventSourcing.Oracle
Register the event store and (optionally) the snapshot store with a connection factory:
using Microsoft.Extensions.DependencyInjection;
using Oracle.ManagedDataAccess.Client;
services.AddOracleEventStore(
() => new OracleConnection(connectionString),
schema: "EXCALIBUR",
table: "EVENTSTOREEVENTS");
services.AddOracleSnapshotStore(
() => new OracleConnection(connectionString),
schema: "EXCALIBUR",
table: "EVENTSTORESNAPSHOTS");
Or configure via options, validated at startup:
services.AddOracleEventStore(options =>
{
options.ConnectionString = connectionString;
options.Schema = "EXCALIBUR";
options.Table = "EVENTSTOREEVENTS";
});
Batch appends are atomic — a multi-row append is all-or-nothing, so a mid-batch failure never leaves a torn event-stream prefix.
Outbox
dotnet add package Excalibur.Outbox.Oracle
The Oracle outbox is registered through the outbox builder with UseOracle:
services.AddExcalibur(x => x.AddOutbox(outbox =>
{
outbox.UseOracle(oracle =>
{
oracle.ConnectionString(connectionString)
.SchemaName("messaging")
.TableName("outbox_messages")
.ReservationTimeout(TimeSpan.FromMinutes(10))
.MaxAttempts(5);
})
.EnableBackgroundProcessing();
}));
A connection can also be resolved from the container via ConnectionFactory(sp => ...).
Inbox
dotnet add package Excalibur.Inbox.Oracle
services.AddOracleInboxStore(options =>
{
options.ConnectionString = connectionString;
options.SchemaName = "messaging";
options.TableName = "inbox_messages";
});
An overload accepts a connection-factory provider (Func<IServiceProvider, Func<OracleConnection>>) when the connection is built from other registered services.
Sagas
dotnet add package Excalibur.Saga.Oracle
services.AddOracleSagaStore(options =>
{
options.ConnectionString = connectionString;
options.SchemaName = "sagas";
});
// Optional: durable saga timeouts
services.AddOracleSagaTimeoutStore(options =>
{
options.ConnectionString = connectionString;
});
Completed sagas can be purged on a retention window via the saga automatic-cleanup background service (SagaOptions.EnableAutomaticCleanup), consistent with the other saga providers. See Sagas → Retention & Cleanup.
SQL Injection Protection
Schema and table names supplied via configuration are validated and quoted, so they cannot be used to inject SQL — the same protection applied by the SQL Server and PostgreSQL providers.
What's Next
- Event Sourcing — Aggregates, event stores, and snapshots
- Outbox Pattern — Reliable message publishing
- Sagas — Long-running process orchestration