Cohesive.Adapters.Marten 0.1.0-alpha.158

This is a prerelease version of Cohesive.Adapters.Marten.
dotnet add package Cohesive.Adapters.Marten --version 0.1.0-alpha.158
                    
NuGet\Install-Package Cohesive.Adapters.Marten -Version 0.1.0-alpha.158
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cohesive.Adapters.Marten" Version="0.1.0-alpha.158" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cohesive.Adapters.Marten" Version="0.1.0-alpha.158" />
                    
Directory.Packages.props
<PackageReference Include="Cohesive.Adapters.Marten" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cohesive.Adapters.Marten --version 0.1.0-alpha.158
                    
#r "nuget: Cohesive.Adapters.Marten, 0.1.0-alpha.158"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cohesive.Adapters.Marten@0.1.0-alpha.158
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cohesive.Adapters.Marten&version=0.1.0-alpha.158&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Cohesive.Adapters.Marten&version=0.1.0-alpha.158&prerelease
                    
Install as a Cake Tool

Cohesive.Adapters.Marten

Marten realizes Cohesive entity history on PostgreSQL. Cohesive owns the canonical entity, transition decision, replacement action, reconstitution and operation receipt contracts; Marten owns stream storage, versions and event schema. The ordinary PostgreSQL adapter has no Marten dependency. Applications opt into this package when attaching event history.

Attach to native storage

using var store = DocumentStore.For(options =>
{
    options.Connection(database); // The same caller-owned NpgsqlDataSource as relational storage.
    options.DatabaseSchemaName = "cohesive_events";
    options.AutoCreateSchemaObjects = JasperFx.AutoCreate.None;
    options.UseCohesiveEntityHistory();
});
// Explicit development migration; production deployments own their migration lifecycle.
await store.Storage.ApplyAllConfiguredChangesToDatabaseAsync();
var history = await MartenEntityHistoryStorage.BindAsync(
    database, store, EntityStateAuthority.Events);
var services = persistence.ForServices(receipts, history, outbox);

BindAsync validates Marten's schema before traffic; it performs no migration. Keep the native data source and store alive for the attachment lifetime. Configure AutoCreate.None to prevent implicit native migrations. Native Marten configuration remains available.

Storage-model preparation

Declare bindings.History(new MartenEntityHistoryConfiguration(authority, reconstitution)) alongside bindings.Outbox(options) and receipts. Both native and composite service preparation borrow the IDocumentStore keyed by the existing database resource name from DI and require the exact relational NpgsqlDataSource before any history DDL. Clients remain DI-owned; model construction performs no IO.

ValidateOnly is the default. Explicit initialization: PostgresSchemaInitialization.CreateIfMissing uses native Marten AutoCreate.CreateOnly, followed by schema validation. It does not update or remove existing objects. This covers all objects configured in that store, so dedicate the store to history if schema ownership must be isolated. Keep AutoCreate.None on the native store. Cancellation reaches native preparation, reconnection retries are disabled, and a failure may leave created objects behind; inspect and repair before rebuilding the host. No lifecycle callback disposes borrowed clients. Authority/reconstitution are immutable model policy; changing authority on existing streams still requires an explicit migration. Product tables, delivery workers and retention are outside this initialization.

One commit boundary

The PostgreSQL repository owns a connection and transaction. Each Marten session enlists through SessionOptions.ForTransaction(transaction, shouldAutoCommit: false). Saving a session flushes the event append but does not commit the transaction. Relational state, Marten events and the operation receipt commit together. For direct entity emissions, relational state, Marten events and the existing outbox commit together instead. Process-owned emissions remain in the operation receipt; they are not also published by the direct outbox.

The adapter introduces no generic transaction coordinator or second receipt model. A subject advisory lock coordinates relational projection rebuilds with writes; Marten also checks the expected stream version on append. Canonical semantic versions remain separate from stream positions and PostgreSQL row tokens. No implicit retries occur. A connection failure during commit is ambiguous: resolve the original operation/emission identities before retrying.

Authority and replay

State authority reads current relational rows and retains events as audit evidence. Event authority reads Marten streams; relational rows are synchronous query projections. The event is a complete canonical replacement action, not an invented business event. Its envelope retains the authority, lossless codec version and payload integrity hash. Exact entity, partition, shape and position validation precede acceptance. Changing authority on a retained stream is rejected when that stream is acquired for a write/read; it is not a database-wide startup scan.

Full replay validates the complete bounded stream. Checkpoint-and-tail starts at an exact retained replacement event at the configured cadence. Marten's event index supplies that position; there is no custom head/action/checkpoint table or duplicate snapshot store. This first slice does not use Marten's aggregate projection/reducer model or async daemon.

Action-count admission occurs before fetching the selected stream range. Payload-byte limits apply to canonical payload decoding and appending; Marten buffers the fetched event objects, so these are not hard limits on network acquisition or peak memory in a maliciously modified database. No throughput or allocation improvement is claimed.

Evidence and limits

The PostgreSQL conformance suite runs against real PostgreSQL and covers replay, concurrent writers, projection rebuilding, missing/corrupt events, setup schema rejection and late receipt/outbox failures. Deferred-trigger tests reject COMMIT after event, relational and evidence writes, then check all participants from fresh connections. The Aspire HTTP test uses the same OrderApi and transition under both authority modes.

There is no external delivery, arbitrary domain-event reducer, tombstone, retention policy, cross-database atomicity or asynchronous CQRS projection in this slice. Native SQL and direct Marten writes bypass the Cohesive protocol. See the example walkthrough.

The envelope stores the canonical action as a JSON object in jsonb, not base64; native projections can inspect that payload, although this adapter does not configure Marten projections. Binding checks the registered event type as well as stream identity and exact data source. This unreleased envelope revision requires explicit migration of earlier byte-array events (including uppercase hashes).

Replay limits are write admission limits too: a full-replay stream cannot append past its configured action or byte budget. Checkpoint cadence must fit the action budget. Cumulative canonical byte counts are retained independently of replay mode; appends acquire the previous event and, when needed, the checkpoint predecessor to check the selected range without decoding the entire stream. This adds bounded metadata acquisition; no write-throughput improvement is claimed. Read-side integrity and range bounds remain independently checked. Outbox byte-limited reads return a partial page with its last included sequence; an individually oversized or corrupt commit still fails rather than being silently skipped.

Model-owned native expectations

MartenEntityHistoryConfiguration declares the document/event schema (schemaName, default public) as well as authority, reconstitution and initialization. Apply Configure(options) when constructing the native DI-owned store; the host still supplies its connection and lifetime. Preparation rejects mismatched schemas, automatic schema changes, stream identity or event registration before native I/O. Validation-only remains the default; CreateIfMissing must be explicit. Use a dedicated history store because native initialization covers its configured objects.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-alpha.158 37 10/24/2026
0.1.0-alpha.157 39 10/24/2026
0.1.0-alpha.156 43 10/22/2026
0.1.0-alpha.155 46 10/20/2026
0.1.0-alpha.154 38 10/20/2026
0.1.0-alpha.153 55 10/20/2026