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
Methods
SavingChanges(DbContextEventData, InterceptionResult<int>)
Called at the start of
public InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
Parameters
eventDataDbContextEventDataContextual information about the DbContext being used.
resultInterceptionResult<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
resultvalue 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
eventDataDbContextEventDataContextual information about the DbContext being used.
resultInterceptionResult<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.
cancellationTokenCancellationTokenA 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
resultvalue 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
transactionDbTransactionThe transaction.
eventDataTransactionEventDataContextual information about connection and transaction.
resultInterceptionResultRepresents 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.
cancellationTokenCancellationTokenA 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
resultvalue passed in.
Exceptions
- OperationCanceledException
If the CancellationToken is canceled.