DKNet

DKNet.AspCore.Idempotency.Relational

Internal EF Core storage machinery shared by the SQL Server and PostgreSQL idempotency providers.

✨ Why use it?

πŸš€ Quick Start

This package is a transitive dependency of the SQL providers. Every type is internal; it exposes no application registration method. Install a provider to exercise it:

dotnet new web -f net10.0 -n PackageDemo
cd PackageDemo
dotnet add package DKNet.AspCore.Idempotency.Relational
dotnet add package DKNet.AspCore.Idempotency.NpgsqlStore

Set ConnectionStrings__Idempotency to a PostgreSQL connection string for a database the app can migrate. Then use this Program.cs and run dotnet run:

using DKNet.AspCore.Idempotency;
using DKNet.AspCore.Idempotency.NpgsqlStore;
var builder = WebApplication.CreateBuilder(args);
var connection = builder.Configuration.GetConnectionString("Idempotency")
    ?? throw new InvalidOperationException("Set ConnectionStrings__Idempotency.");
builder.Services.AddIdempotencyWithNpgsqlStore(connection);
var app = builder.Build();
app.MapPost("/orders", () => Results.Ok()).RequiredIdempotentKey();
await app.RunAsync();

POST twice with X-Idempotency-Key: order-1: the first returns 200 and the retry 409. The provider applies its migrations on host start.

πŸ—οΈ Architecture

Concrete SQL providers select the shared relational store, which creates contexts and reads or writes IdempotencyKeys.

The public surface is empty. Application code registers a concrete provider; its singleton store holds a private async scope and uses a new EF context per operation.

πŸ”„ How it works

The host registers the SQL provider, applies pending migrations, then validates and reserves each protected request before running and retaining its result.

A successful insert returns new immediately. The unique-violation branch alone reads the blocking row. Neither expiry nor completion is a transaction with the application’s business writes.

🧩 Features