Perigon.PostgreSQL
0.1.1
See the version list below for details.
dotnet add package Perigon.PostgreSQL --version 0.1.1
NuGet\Install-Package Perigon.PostgreSQL -Version 0.1.1
<PackageReference Include="Perigon.PostgreSQL" Version="0.1.1" />
<PackageVersion Include="Perigon.PostgreSQL" Version="0.1.1" />
<PackageReference Include="Perigon.PostgreSQL" />
paket add Perigon.PostgreSQL --version 0.1.1
#r "nuget: Perigon.PostgreSQL, 0.1.1"
#:package Perigon.PostgreSQL@0.1.1
#addin nuget:?package=Perigon.PostgreSQL&version=0.1.1
#tool nuget:?package=Perigon.PostgreSQL&version=0.1.1
Perigon.PostgreSQL
Perigon.PostgreSQL is a PostgreSQL-only data access library for .NET applications. It provides an EF Core-like DbContext / DbSet<T> programming model while keeping the runtime small, explicit, and NativeAOT-friendly.
The library is designed for services that want predictable PostgreSQL SQL, no change tracking, no lazy loading, and direct access to PostgreSQL features such as arrays, JSONB, COPY, ON CONFLICT, and RETURNING.
Goals
- PostgreSQL-only behavior built on Npgsql.
- NativeAOT-aware metadata, materialization, and write accessors through source generation.
- Deterministic SQL with
$1,$2, ... positional parameters. - No change tracking and no implicit client-side LINQ fallback.
- Compile-time analyzer warnings for common unsupported or unsafe query shapes.
- Simple use from console apps, workers, and ASP.NET Core apps.
Current Capabilities
- Entity mapping by convention or with
[Table]/[Column]attributes. - LINQ query translation for common
Where, ordering, paging, projection, distinct, joins, grouping, aggregates, arrays, and JSONB extensions. - Async query execution with
ToListAsync, scalar projections,CountAsync,AnyAsync,FirstOrDefaultAsync, andSingleOrDefaultAsync. - Insert, update, delete, bulk insert, insert returning, and upsert APIs.
- PostgreSQL-native array operations:
ANY,@>,&&,<@,cardinality, and array aggregates. - PostgreSQL JSONB operations: containment, key exists, text extraction, and JSONPath exists.
- Raw SQL query and command APIs using interpolated parameters.
- Split-query association loading through
IncludeManyAsync. - Source generator and analyzer are included in the main NuGet package.
Unsupported query shapes throw clear exceptions instead of falling back to client evaluation. Some examples are local method calls inside queries, Expression.Invoke, dynamic JSON POCO mapping, lazy loading, and arbitrary object graph JSON mapping without a source-generated path.
Install
From NuGet:
dotnet add package Perigon.PostgreSQL
For local package testing from this repository:
.\scripts\pack.ps1
dotnet nuget add source .\artifacts\packages --name PerigonLocal
dotnet add package Perigon.PostgreSQL --version 1.0.0 --source PerigonLocal
To create a different package version:
.\scripts\pack.ps1 -Version 1.0.1
When repeatedly testing local packages, use a new -Version value or clear the NuGet global package cache so the consuming project restores the latest nupkg.
The package includes:
lib/net10.0/Perigon.PostgreSQL.dllanalyzers/dotnet/cs/Perigon.PostgreSQL.SourceGeneration.dllanalyzers/dotnet/cs/Perigon.PostgreSQL.Analyzers.dll
Define a Model
using Perigon.PostgreSQL.Attributes;
[Table("users")]
public sealed class User
{
[Column("id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[Column("user_name")]
public string UserName { get; set; } = "";
[Column("age")]
public int Age { get; set; }
[Column("tags", IsArray = true)]
public string[]? Tags { get; set; }
[Column("profile_json", TypeName = "jsonb")]
public string? ProfileJson { get; set; }
}
Define a Context
using Perigon.PostgreSQL;
public sealed class AppDbContext : DbContext
{
public AppDbContext(string connectionString)
: base(options => options.UsePostgres(connectionString))
{
}
public DbSet<User> Users => Set<User>();
}
Console App Example
using Perigon.PostgreSQL;
var connectionString = "Host=localhost;Port=5432;Database=app;Username=postgres;Password=postgres";
await using var db = new AppDbContext(connectionString);
var activeUsers = await db.Users
.Where(user => user.Age >= 18 && user.Tags!.Contains("postgres"))
.OrderBy(user => user.UserName)
.Take(20)
.ToListAsync();
var inserted = await db.Users.InsertAsync(new User
{
UserName = "alice",
Age = 31,
Tags = ["developer", "postgres"],
ProfileJson = """{"level":3}"""
});
ASP.NET Core Example
using Perigon.PostgreSQL;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("Postgres")
?? "Host=localhost;Port=5432;Database=app;Username=postgres;Password=postgres";
builder.Services.AddDbContext(_ => new AppDbContext(connectionString));
var app = builder.Build();
app.MapGet("/users", async (AppDbContext db, string? tag) =>
{
IQueryable<User> query = db.Users;
if (!string.IsNullOrWhiteSpace(tag))
{
query = query.Where(user => user.Tags!.Contains(tag));
}
return await query
.OrderBy(user => user.UserName)
.ToListAsync();
});
app.MapPost("/users", async (AppDbContext db, User user) =>
Results.Created($"/users/{user.Id}", await db.Users.InsertAsync(user)));
app.Run();
AddDbContext registers the context as scoped by default. The factory form keeps construction explicit and NativeAOT-friendly.
Query Examples
Arrays:
var users = await db.Users
.Where(user => user.Tags!.Contains("postgres"))
.ToListAsync();
JSONB:
var users = await db.Users
.Where(user => user.ProfileJson.JsonbPathExists("$.level ? (@ > 2)"))
.ToListAsync();
Update and delete require a filter unless you explicitly opt in to full-table mutations:
await db.Users
.Where(user => user.UserName == "alice")
.ExecuteUpdateAsync(setters => setters.Set(user => user.Age, 32));
await db.Users
.Where(user => user.UserName == "alice")
.ExecuteDeleteAsync();
Raw SQL remains parameterized when using interpolated strings:
var name = "alice";
var users = await db.SqlQuery<User>($"SELECT * FROM users WHERE user_name = {name}")
.ToListAsync();
Analyzer Warnings
The package automatically enables analyzers in consuming projects. Current warnings include:
PG001: update/delete query has no visibleWhere(...)and no explicit full-table option.PG002: query expression contains clearly unsupported method calls, such as local methods,Expression.Invoke,System.Math, or culture-aware string overloads.PG003: JSONB property uses dynamic POCO mapping instead ofstring,JsonDocument,JsonElement, or a source-generated JSON path.
Sample Project
The repository includes an ASP.NET Core minimal API sample:
samples/Perigon.PostgreSQL.AspNetCoreSample
Run PostgreSQL for the sample:
cd .\samples\Perigon.PostgreSQL.AspNetCoreSample
docker compose up -d
Run the API from the repository root:
dotnet run --project .\samples\Perigon.PostgreSQL.AspNetCoreSample\Perigon.PostgreSQL.AspNetCoreSample.csproj --urls http://localhost:5088
Seed and query data:
Invoke-RestMethod -Method Post http://localhost:5088/seed
Invoke-RestMethod "http://localhost:5088/users?status=active&tag=postgres&minAge=18"
Invoke-RestMethod "http://localhost:5088/users/with-blogs?status=active&publicOnly=true"
Repository
Source code and sample projects are available at:
https://github.com/AterDev/Perigon.PostgreSQL
| 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
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- Npgsql (>= 10.0.0)
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 |
|---|---|---|
| 0.1.4 | 93 | 5/30/2026 |
| 0.1.3 | 92 | 5/29/2026 |
| 0.1.2 | 94 | 5/28/2026 |
| 0.1.1 | 112 | 5/27/2026 |
| 0.1.0 | 89 | 5/27/2026 |
| 0.1.0-preview2 | 92 | 5/26/2026 |
| 0.1.0-preview1 | 88 | 5/26/2026 |
Preview 2 expands real PostgreSQL integration coverage, adds raw SQL and
source generator unit tests, and fixes JSONB containment SQL casting. See RELEASE_NOTES.md for
details.