https://github.com/pandatecham/be-lib-sharedkernel-postgres
Most common utilities used in every project by PandaTech + Postgres extensions
https://github.com/pandatecham/be-lib-sharedkernel-postgres
Last synced: about 2 months ago
JSON representation
Most common utilities used in every project by PandaTech + Postgres extensions
- Host: GitHub
- URL: https://github.com/pandatecham/be-lib-sharedkernel-postgres
- Owner: PandaTechAM
- License: mit
- Created: 2024-11-21T16:05:51.000Z (over 1 year ago)
- Default Branch: development
- Last Pushed: 2026-03-19T10:30:16.000Z (3 months ago)
- Last Synced: 2026-03-19T21:21:21.339Z (3 months ago)
- Language: C#
- Size: 5.57 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Pandatech.SharedKernel.Postgres
PostgreSQL integration helpers for ASP.NET Core 10. Wraps Npgsql, Entity Framework Core, health checks, exception
mapping, query locks, snake_case naming, and audit trail wiring into a small set of extension methods so every service
starts from the same consistent baseline.
Requires **.NET 10.0**. Uses C# 14 extension members and cannot be downgraded.
---
## Table of Contents
1. [Installation](#installation)
2. [What is included](#what-is-included)
3. [Registering a DbContext](#registering-a-dbcontext)
4. [Migrations](#migrations)
5. [Model configuration helpers](#model-configuration-helpers)
6. [Health checks](#health-checks)
---
## Installation
```bash
dotnet add package Pandatech.SharedKernel.Postgres
```
---
## What is included
Every `AddPostgresContext*` overload automatically applies the following to your DbContext:
| Feature | Source package |
|-----------------------------------|---------------------------------------------|
| Npgsql provider | `Npgsql.EntityFrameworkCore.PostgreSQL` |
| Snake_case naming convention | `EFCore.NamingConventions` |
| Query locks (`FOR UPDATE` etc.) | `Pandatech.EFCore.PostgresExtensions` |
| Friendly exception mapping | `EntityFrameworkCore.Exceptions.PostgreSQL` |
| `AuditBase` property validation | `Pandatech.EFCore.AuditBase` |
| Audit trail interceptors (opt-in) | `Pandatech.EFCore.Audit` |
| Postgres health check | `AspNetCore.HealthChecks.NpgSql` |
| Bulk extensions | `EFCore.BulkExtensions.PostgreSql` |
| Gridify query extensions | `Pandatech.GridifyExtensions` |
---
## Registering a DbContext
All overloads are on `WebApplicationBuilder` and return `WebApplicationBuilder` for chaining. Every variant
automatically registers a Postgres health check named `postgres_{DatabaseName}`.
### Basic registration (no pooling, no audit trail)
```csharp
// Minimal — connection string only
builder.AddPostgresContext(connectionString);
// With migrations assembly by name
builder.AddPostgresContext(connectionString, "MyApp.Migrations");
// With migrations assembly by Assembly reference
builder.AddPostgresContext(connectionString, typeof(Program).Assembly);
// With migrations assembly by marker type
builder.AddPostgresContext(connectionString);
// Full control via NpgsqlDbContextOptionsBuilder callback
builder.AddPostgresContext(connectionString, npgsql =>
{
npgsql.MigrationsAssembly("MyApp.Migrations");
npgsql.CommandTimeout(60);
});
```
### With connection pooling
Same set of overloads, prefixed with `Pool`:
```csharp
builder.AddPostgresContextPool(connectionString);
builder.AddPostgresContextPool(connectionString, "MyApp.Migrations");
builder.AddPostgresContextPool(connectionString);
builder.AddPostgresContextPool(connectionString, npgsql => { ... });
```
Use pooling for high-throughput services. Note that DbContext pooling requires that your context has no scoped
dependencies injected via the constructor; use service provider overloads (`(sp, options) => ...`) for those cases.
### With audit trail (no pooling)
Registers the `Pandatech.EFCore.Audit` interceptors alongside the standard options:
```csharp
builder.AddPostgresContextWithAuditTrail(connectionString);
builder.AddPostgresContextWithAuditTrail(connectionString, "MyApp.Migrations");
builder.AddPostgresContextWithAuditTrail(connectionString);
builder.AddPostgresContextWithAuditTrail(connectionString, npgsql => { ... });
```
### With pooling and audit trail
```csharp
builder.AddPostgresContextPoolWithAuditTrail(connectionString);
builder.AddPostgresContextPoolWithAuditTrail(connectionString, "MyApp.Migrations");
builder.AddPostgresContextPoolWithAuditTrail(connectionString);
builder.AddPostgresContextPoolWithAuditTrail(connectionString, npgsql => { ... });
```
---
## Migrations
Apply pending migrations at startup:
```csharp
// Synchronous
app.MigrateDatabase();
// Asynchronous
await app.MigrateDatabaseAsync(ct);
```
Both create a scoped service provider, resolve the context, and call `Database.Migrate` / `Database.MigrateAsync`.
Place these calls after `app.Build()` and before `app.Run()`.
---
## Model configuration helpers
Add to `ConfigureConventions` and `OnModelCreating` in your DbContext:
```csharp
protected override void ConfigureConventions(ModelConfigurationBuilder builder)
{
// Map all decimal properties to NUMERIC(40, 20) — prevents precision loss
builder.ConfigureDecimalType();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Set all foreign key delete behavior to Restrict (no accidental cascades)
modelBuilder.RestrictFkDeleteBehaviorByDefault();
}
```
`ConfigureDecimalType` sets precision `(40, 20)` globally. Override individual properties via `[Precision]` or fluent
API if you need a narrower type for a specific column.
`RestrictFkDeleteBehaviorByDefault` iterates all foreign keys at model build time and sets `DeleteBehavior.Restrict`.
Override individual relationships fluently after this call if cascade delete is intentionally needed.
---
## Health checks
The health check is registered automatically by every `AddPostgresContext*` overload. It uses
`AspNetCore.HealthChecks.NpgSql` with a 5-second timeout and is named `postgres_{DatabaseName}` where the database
name is parsed from the connection string.
To expose the health check endpoint, use `MapHealthCheckEndpoints()` from `Pandatech.SharedKernel`:
```csharp
app.MapHealthCheckEndpoints(); // /above-board/health
```
Or register your own endpoint:
```csharp
app.MapHealthChecks("/health");
```
If the database name cannot be parsed from the connection string, registration throws `ArgumentException` at startup
rather than silently registering a misnamed check.
---
## License
MIT