Sencilla.Messaging.EntityFramework 10.0.62

dotnet add package Sencilla.Messaging.EntityFramework --version 10.0.62
                    
NuGet\Install-Package Sencilla.Messaging.EntityFramework -Version 10.0.62
                    
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="Sencilla.Messaging.EntityFramework" Version="10.0.62" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sencilla.Messaging.EntityFramework" Version="10.0.62" />
                    
Directory.Packages.props
<PackageReference Include="Sencilla.Messaging.EntityFramework" />
                    
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 Sencilla.Messaging.EntityFramework --version 10.0.62
                    
#r "nuget: Sencilla.Messaging.EntityFramework, 10.0.62"
                    
#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 Sencilla.Messaging.EntityFramework@10.0.62
                    
#: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=Sencilla.Messaging.EntityFramework&version=10.0.62
                    
Install as a Cake Addin
#tool nuget:?package=Sencilla.Messaging.EntityFramework&version=10.0.62
                    
Install as a Cake Tool

Sencilla.Messaging.EntityFramework

The database as a durable messaging transport. Messages become rows in [Message]; workers claim them, run the registered handler, and acknowledge the outcome — so a message survives a worker crash, retries with backoff, and ends in a state an operator can query.

Use it when the work must not be lost: background jobs, long-running operations, anything whose failure has to be visible afterwards. For fire-and-forget notifications between processes, a broker transport (RabbitMQ) is lighter.

Enqueueing is transactional, and deliberately not the dispatcher

using var tx = await projects.BeginTransaction(token);

var project = await projects.Create(new Project { ... }, token);
await queue.Enqueue(new Message<CloneProject> { EntityId = project.Id, UserId = user.Id, Payload = new(...) }, "tasks", token: token);

await tx.CommitAsync(token);   // row and message commit together, or neither does

IMessageQueue is scoped: it writes through the caller's DbContext, so the message lands in the caller's transaction. IMessageDispatcher cannot do this — it is a singleton and cannot reach the caller's scope — which is why durable enqueue has its own API. The distinction is the point: one call is transactional, the other is not, and you can see which is which at the call site.

The [Message] table carries no user grants, so callers outside a request identity wrap the enqueue in Access.Root() — their own endpoint or worker is the authorization.

Handling

An ordinary handler, autoscanned like any other:

public class CloneProjectHandler(...) : IMessageHandler<Message<CloneProject>>
{
    public async Task HandleAsync(Message<CloneProject> message, CancellationToken token) { ... }
}

Return normally and the message is acked. Throw and it is re-queued with backoff until MaxAttempts, then marked Failed. Terminal failures raise MessageFailed<T>, so app-side surfacing (flip a status, write a notification) is just another handler:

public class CloneProjectFailedHandler(...) : IMessageHandler<MessageFailed<CloneProject>> { ... }

Delivery is at-least-once. A crash between a handler finishing and the ack re-runs it, so handlers must be idempotent.

Wiring

services.AddSencillaMessaging(o =>
{
    o.UseMediator();
    o.UseEntityFramework(ef =>
    {
        ef.WithOptions(configuration);            // binds the "Messaging" section
        ef.AddStreams(s => s.AddQueue("tasks"));
        ef.AddConsumers(c => c.ForStream("tasks", _ => _.MaxConcurrentHandlers = 1));
    });
});

A host that only enqueues (a web app) declares the streams but no consumers. A worker declares consumers too.

Recovery and instance identity

Messaging:InstanceId must be unique per process — it defaults to the machine/pod name, which is already unique per pod under Kubernetes. Two replicas sharing an id means one re-queues rows the other is actively processing.

Recovery has two layers:

  • On start, an instance re-queues anything left InProgress under its own name. A fresh process owns nothing in flight, so this is immediate and needs no claim cache.
  • By age, rows InProgress longer than StuckAfterMinutes are re-queued regardless of owner — the instance that never comes back is exactly the case owner-scoped recovery cannot handle. Keep the threshold above the longest legitimate handler runtime.

Options (Messaging section)

Option Default
InstanceId machine name claim identity; unique per process
PollIntervalSeconds 20 sleep when the stream is empty
MaxAttempts 3 attempts before Failed
RetryBaseDelaySeconds / UseExponentialBackoff 2 / true retry spacing
StuckAfterMinutes 30 age-based rescue threshold
RetentionDays / RetentionSweepMinutes 90 / 60 terminal-row cleanup; 0 disables

Schema

Sencilla.Messaging.EntityFramework.Mssql ships the [Message] table into your dacpac. No seed data and no lookup tables — adding a message type touches no SQL at all.

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
10.0.62 70 9/9/2026
10.0.61 63 9/9/2026
10.0.59 96 8/21/2026
10.0.58 91 8/21/2026
10.0.57 90 8/21/2026
10.0.56 96 8/21/2026
10.0.55 96 8/18/2026
10.0.54 92 8/14/2026
10.0.53 94 8/10/2026
10.0.52 97 8/7/2026
10.0.51 97 8/5/2026
10.0.50 91 8/5/2026
10.0.49 113 7/31/2026
10.0.48 113 7/23/2026
10.0.47 110 7/17/2026
10.0.46 103 7/13/2026
10.0.45 112 7/5/2026
10.0.44 114 6/23/2026
10.0.43 102 6/23/2026
10.0.42 110 6/22/2026
Loading failed