DcsvIo.D2.EntityFrameworkCore.Postgres
0.1.1
dotnet add package DcsvIo.D2.EntityFrameworkCore.Postgres --version 0.1.1
NuGet\Install-Package DcsvIo.D2.EntityFrameworkCore.Postgres -Version 0.1.1
<PackageReference Include="DcsvIo.D2.EntityFrameworkCore.Postgres" Version="0.1.1" />
<PackageVersion Include="DcsvIo.D2.EntityFrameworkCore.Postgres" Version="0.1.1" />
<PackageReference Include="DcsvIo.D2.EntityFrameworkCore.Postgres" />
paket add DcsvIo.D2.EntityFrameworkCore.Postgres --version 0.1.1
#r "nuget: DcsvIo.D2.EntityFrameworkCore.Postgres, 0.1.1"
#:package DcsvIo.D2.EntityFrameworkCore.Postgres@0.1.1
#addin nuget:?package=DcsvIo.D2.EntityFrameworkCore.Postgres&version=0.1.1
#tool nuget:?package=DcsvIo.D2.EntityFrameworkCore.Postgres&version=0.1.1
DcsvIo.D2.EntityFrameworkCore.Postgres
Audience: backend .NET service engineers wiring a PostgreSQL-backed EF Core DbContext with advisory-lock-guarded migrations and startup validation.
PostgreSQL-specific EF Core startup machinery shared across all D2 services.
Each service that owns a per-domain database registers
AdvisoryLockMigrator<TContext> to safely bootstrap migrations across multiple
replicas, and calls ApplyD2NpgsqlDefaults from both the DI registration and the
design-time factory so the two paths can never drift.
Mechanism only. Domain advisory-lock key catalogs do not ship from this
package. Callers pass domain-owned generated constants (e.g.
AdvisoryLocks.SampleDomain.MIGRATOR from the owning host/module assembly) into
PgAdvisoryLock / AdvisoryLockMigrator. The fleet catalog SoT remains
contracts/advisory-locks/;
DcsvIo.D2.AdvisoryLocks.SourceGen emits into the owning-module
assembly.
Install
dotnet add package DcsvIo.D2.EntityFrameworkCore.Postgres
PgAdvisoryLock
Session-scoped PostgreSQL advisory lock helper. Opens a dedicated
NpgsqlConnection; each acquired lock scope owns its connection lifecycle.
// Try-acquire (non-blocking — skip if held):
// Pass a domain-owned generated constant from the owning host/module assembly.
await using var rotLock = await PgAdvisoryLock.TryAcquireSessionAsync(
connStr, migratorLockKey /* e.g. AdvisoryLocks.MyService.ROTATION */, ct);
if (!rotLock.IsHeld)
return; // another instance is rotating — skip this tick
// Blocking acquire (migrator):
await using var migLock = await PgAdvisoryLock.AcquireSessionBlockingAsync(
connStr, migratorLockKey /* e.g. AdvisoryLocks.MyService.MIGRATOR */, ct);
// migLock.IsHeld is always true after this returns
PgAdvisoryLock is [MustDisposeResource] — always use await using. DisposeAsync
sends an explicit pg_advisory_unlock and closes the connection.
No EnableRetryOnFailure: an execution-strategy reconnect silently drops a session
lock. Services using advisory locks must handle transient failures at the application
level.
AdvisoryLockMigrator<TContext>
IHostedService that runs at host startup: ensure-database → blocking lock → migrate
→ release.
Register it before any hosted services that require the schema:
services.AddSingleton<AdvisoryLockMigrator<MyDbContext>>(sp =>
new AdvisoryLockMigrator<MyDbContext>(
sp.GetRequiredService<IServiceScopeFactory>(),
connectionString,
migratorLockKey, // domain-owned generated AdvisoryLocks.{Db}.MIGRATOR
sp.GetRequiredService<ILogger<AdvisoryLockMigrator<MyDbContext>>>()));
services.AddHostedService<AdvisoryLockMigrator<MyDbContext>>();
The migrator is fail-fast: a bad migration throws, crash-looping the host so the problem surfaces immediately rather than starting with a corrupt schema.
DesignTimeDbContextFactoryBase<TContext>
Abstract base for EF Core design-time factories in module-within-host services (no
Sdk.Web startup project for dotnet ef). Subclass in the infra/ project:
public sealed class MyDbContextFactory
: DesignTimeDbContextFactoryBase<MyDbContext>
{
protected override string ConnectionStringEnvVar => "MY_DATABASE_URL";
protected override string MigrationsAssemblyName =>
typeof(MyDbContextFactory).Assembly.GetName().Name!;
protected override MyDbContext CreateContext(DbContextOptions<MyDbContext> opts)
=> new(opts);
}
Set MY_DATABASE_URL before running dotnet ef migrations add <Name>.
NpgsqlContextDefaults.ApplyD2NpgsqlDefaults
Canonical DbContextOptionsBuilder extension that applies UseNpgsql with
AddD2NodaTime(), CommandTimeout, and MigrationsAssembly. Call from BOTH the
runtime DI lambda AND the design-time factory so neither path can drift.
EnableRetryOnFailure is intentionally absent — see PgAdvisoryLock remarks above.
Configuration
No configuration of its own. Consumers supply:
connectionString— the Npgsql connection string (e.g. fromMY_DATABASE_URL).commandTimeoutSeconds— per-command timeout (seconds).migrationsAssemblyName— assembly holding the EF Core migrations.migratorLockKey— advisory lock bigint key for the migrator (domain-owned generatedAdvisoryLocks.*constant from the owning module assembly).
Dependencies
Microsoft.EntityFrameworkCore—DbContext,Database.MigrateAsync, design-timeIDesignTimeDbContextFactory.Npgsql.EntityFrameworkCore.PostgreSQL—UseNpgsql,NpgsqlDbContextOptionsBuilder.Npgsql— rawNpgsqlConnectionfor advisory locks and ensure-db maintenance.DcsvIo.D2.Time—AddD2NodaTime()(NodaTime ↔TIMESTAMPTZvalue converters).DcsvIo.D2.Utilities—ThrowIfFalsey/Falseyguards.JetBrains.Annotations—[MustDisposeResource]onPgAdvisoryLock.
| Product | Versions 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. |
-
net10.0
- DcsvIo.D2.Time (>= 0.1.1)
- DcsvIo.D2.Utilities (>= 0.1.1)
- dotenv.net (>= 4.0.2)
- JetBrains.Annotations (>= 2025.2.4)
- Microsoft.EntityFrameworkCore (>= 10.0.7)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.7)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Caching.Memory (>= 10.0.7)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.7)
- Microsoft.Extensions.DependencyInjection (>= 10.0.7)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Logging (>= 10.0.7)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Options (>= 10.0.7)
- NodaTime (>= 3.2.2)
- Npgsql (>= 10.0.2)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.1)
- Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime (>= 10.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.