Skip to main content
Table of Contents

Class CommitCompletionInterceptor

Namespace
Stratara.EventSourcing.EntityFrameworkCore
Assembly
Stratara.EventSourcing.EntityFrameworkCore.dll

Lets a commit, once begun, run to its end whatever the caller's cancellation says. A database driver that is told to cancel while it waits for a commit to be acknowledged may report the cancellation after the database committed; the caller then takes a committed save for one that failed, and whatever runs it — a transport, a retry, a resumed command — runs it again and records the same facts twice. With this interceptor a cancellation is honoured while the changes are written, which leaves nothing behind, and no longer once the commit has begun, so what the caller is told is what happened. A save that would run as a single statement outside a transaction — committed by the database the moment the statement ends, with no commit to let run — is given a transaction as well.

public sealed class CommitCompletionInterceptor : IDbTransactionInterceptor, ISaveChangesInterceptor, IInterceptor
Inheritance
CommitCompletionInterceptor
Implements
Inherited Members
Extension Methods

Remarks

The framework adds it to every context it registers. A context a host registers itself, and that the framework writes through, should add it too:

services.AddDbContextFactory<AppWriteDbContext>(options => options
    .UseNpgsql(connectionString)
    .AddInterceptors(CommitCompletionInterceptor.Instance));

Add it after any transaction interceptor that must act before the commit: it performs the commit in its own TransactionCommittingAsync, and an interceptor that runs after it sees the commit already done. A commit is bounded by the connection's own command timeout (with Npgsql, Command Timeout in the connection string). A context whose AutoTransactionBehavior was set to Never keeps it, and its saves outside an explicit transaction are not covered. The framework's unit of work reads whether a context's options carry this interceptor: on one that does not, it saves without the caller's token at all, so that save runs to its end whole. A host that enables a retrying execution strategy should know that the strategy runs a save again when the acknowledgement of its commit was lost; an append then fails as a concurrency conflict although it committed.

Properties

Instance

The interceptor; it holds no state, so one instance serves every context.

public static CommitCompletionInterceptor Instance { get; }

Property Value

CommitCompletionInterceptor

Methods

SavingChanges(DbContextEventData, InterceptionResult<int>)

Called at the start of .

public InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)

Parameters

eventData DbContextEventData

Contextual information about the DbContext being used.

result InterceptionResult<int>

Represents the current result if one exists. This value will have HasResult set to true if some previous interceptor suppressed execution by calling SuppressWithResult(TResult). This value is typically used as the return value for the implementation of this method.

Returns

InterceptionResult<int>

If HasResult is false, the EF will continue as normal. If HasResult is true, then EF will suppress the operation it was about to perform and use Result instead. An implementation of this method for any interceptor that is not attempting to change the result is to return the result value passed in.

SavingChangesAsync(DbContextEventData, InterceptionResult<int>, CancellationToken)

Called at the start of .

public ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)

Parameters

eventData DbContextEventData

Contextual information about the DbContext being used.

result InterceptionResult<int>

Represents the current result if one exists. This value will have HasResult set to true if some previous interceptor suppressed execution by calling SuppressWithResult(TResult). This value is typically used as the return value for the implementation of this method.

cancellationToken CancellationToken

A CancellationToken to observe while waiting for the task to complete.

Returns

ValueTask<InterceptionResult<int>>

If HasResult is false, the EF will continue as normal. If HasResult is true, then EF will suppress the operation it was about to perform and use Result instead. An implementation of this method for any interceptor that is not attempting to change the result is to return the result value passed in.

Exceptions

OperationCanceledException

If the CancellationToken is canceled.

TransactionCommittingAsync(DbTransaction, TransactionEventData, InterceptionResult, CancellationToken)

Called just before EF intends to call CommitAsync(CancellationToken).

public ValueTask<InterceptionResult> TransactionCommittingAsync(DbTransaction transaction, TransactionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)

Parameters

transaction DbTransaction

The transaction.

eventData TransactionEventData

Contextual information about connection and transaction.

result InterceptionResult

Represents the current result if one exists. This value will have IsSuppressed set to true if some previous interceptor suppressed execution by calling Suppress(). This value is typically used as the return value for the implementation of this method.

cancellationToken CancellationToken

A CancellationToken to observe while waiting for the task to complete.

Returns

ValueTask<InterceptionResult>

If IsSuppressed is false, then EF will continue as normal. If IsSuppressed is true, then EF will suppress the operation it was about to perform. An implementation of this method for any interceptor that is not attempting to suppress the operation is to return the result value passed in.

Exceptions

OperationCanceledException

If the CancellationToken is canceled.