CodeLogic.PostgreSQL 4.5.2-preview.68

This is a prerelease version of CodeLogic.PostgreSQL.
There is a newer version of this package available.
See the version list below for details.
dotnet add package CodeLogic.PostgreSQL --version 4.5.2-preview.68
                    
NuGet\Install-Package CodeLogic.PostgreSQL -Version 4.5.2-preview.68
                    
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="CodeLogic.PostgreSQL" Version="4.5.2-preview.68" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CodeLogic.PostgreSQL" Version="4.5.2-preview.68" />
                    
Directory.Packages.props
<PackageReference Include="CodeLogic.PostgreSQL" />
                    
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 CodeLogic.PostgreSQL --version 4.5.2-preview.68
                    
#r "nuget: CodeLogic.PostgreSQL, 4.5.2-preview.68"
                    
#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 CodeLogic.PostgreSQL@4.5.2-preview.68
                    
#: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=CodeLogic.PostgreSQL&version=4.5.2-preview.68&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=CodeLogic.PostgreSQL&version=4.5.2-preview.68&prerelease
                    
Install as a Cake Tool

CodeLogic.PostgreSQL

NuGet

PostgreSQL database access for CodeLogic applications with multi-database support, a fluent LINQ query builder, an attribute-driven repository, transactions, and automatic table sync / schema migrations with backups.

Install

dotnet add package CodeLogic.PostgreSQL

Quick Start

var pgLib = new PostgreSQLLibrary();
// After library initialization via the CodeLogic framework:

// Define an entity
[Table(Name = "users", Schema = "public")]
public class User
{
    [Column(Primary = true, AutoIncrement = true)]
    public int Id { get; set; }

    [Column(NotNull = true)]
    public string Name { get; set; } = "";

    public bool IsActive { get; set; }
}

// Sync the table schema (creates or alters to match the entity)
await pgLib.SyncTableAsync<User>();

// Typed repository (CRUD)
var repo = pgLib.GetRepository<User>();
var created = await repo.InsertAsync(new User { Name = "Ada", IsActive = true });

// Fluent query builder
var users = await pgLib.Query<User>()
    .Where(u => u.IsActive)
    .OrderBy(u => u.Name)
    .Limit(50)
    .ToListAsync();

// Transactions (auto-rollback on dispose if not committed)
await using var tx = await pgLib.BeginTransactionAsync();
// ... do work ...
await tx.CommitAsync();

All async operations return Result<T> / Result<...> — check IsSuccess / IsFailure and read .Value or .Error.

Features

  • Multi-database support -- manage connections to multiple PostgreSQL instances from one config; pick the connection per call with connectionId.
  • Fluent query builder -- Query<T>() with Where, OrderBy/OrderByDescending, Limit/Offset (Take/Skip), Join, Select, GroupBy, aggregates, paging, and bulk update/delete.
  • Repository pattern -- GetRepository<T>() for full CRUD plus bulk insert, paging, find, and atomic increment/decrement.
  • Attribute-driven schema -- [Table], [Column], [ForeignKey], [CompositeIndex], [Ignore].
  • Table sync and migrations -- create or alter tables to match entities, with timestamped schema backups and JSON migration history.
  • Transactions -- BeginTransactionAsync() returns an await using scope that auto-rolls-back if not committed.
  • Connection pooling -- configurable pool sizes, idle timeout, command/connect timeouts, SSL mode, and slow-query logging.
  • Health checks and events -- HealthCheckAsync() plus published events (table synced, slow query, connect/disconnect, health changed).

Entities and Attributes

[Table(Name = "orders", Schema = "public", Comment = "Customer orders")]
[CompositeIndex("ix_orders_customer_status", "CustomerId", "Status", Unique = false)]
public class Order
{
    [Column(Primary = true, AutoIncrement = true)]
    public int Id { get; set; }

    [Column(NotNull = true, Index = true)]
    public int CustomerId { get; set; }

    [Column(DataType = DataType.Numeric, Precision = 12, Scale = 2)]
    public decimal Total { get; set; }

    [Column(Name = "status", Size = 32, DefaultValue = "'pending'")]
    public string Status { get; set; } = "pending";

    [ForeignKey("customers", "Id", OnDelete = ForeignKeyAction.Cascade)]
    public int FkCustomer { get; set; }

    [Ignore]
    public string? TransientNote { get; set; }
}
  • [Table]Name (defaults to class name), Schema (defaults to public), Comment.
  • [Column]Name, DataType, Size, Precision/Scale, Primary, AutoIncrement (GENERATED ALWAYS AS IDENTITY), NotNull, Unique, Index, DefaultValue, Comment, OnUpdateCurrentTimestamp.
  • [ForeignKey(referenceTable, referenceColumn)]OnDelete / OnUpdate (ForeignKeyAction: Restrict, Cascade, SetNull, NoAction, SetDefault), ConstraintName.
  • [CompositeIndex(indexName, columnNames...)] — multi-column index; Unique optional; repeatable.
  • [Ignore] — excludes a property from reads, writes, and schema sync.

DataType values include SmallInt, Int, BigInt, Real, DoublePrecision, Numeric, Timestamp/TimestampTz, Date, Time/TimeTz, Char, VarChar, Text, Json, Jsonb, Uuid, Bool, Bytea, and array types (IntArray, BigIntArray, TextArray, NumericArray).

Repository

var repo = pgLib.GetRepository<User>();           // optional connectionId argument

await repo.InsertAsync(user);                       // INSERT ... RETURNING *
await repo.InsertManyAsync(users);
await repo.GetByIdAsync(1);
await repo.GetByColumnAsync("Name", "Ada");
await repo.GetAllAsync();
await repo.GetPagedAsync(page: 1, pageSize: 25, orderByColumn: "Name", descending: false);
await repo.CountAsync();
await repo.UpdateAsync(user);                        // by primary key, RETURNING *
await repo.DeleteAsync(1);
await repo.FindAsync(u => u.IsActive);
await repo.IncrementAsync(1, u => u.LoginCount, 1);
await repo.DecrementAsync(1, u => u.Credits, 5);
await repo.RawQueryAsync("SELECT * FROM \"users\" WHERE \"Name\" = @n",
    new() { ["@n"] = "Ada" });
await repo.RawExecuteAsync("UPDATE \"users\" SET \"IsActive\" = false");

A primary key ([Column(Primary = true)]) is required for GetByIdAsync, UpdateAsync, DeleteAsync, and increment/decrement.

Query Builder

var page = await pgLib.Query<User>()
    .Where(u => u.IsActive)
    .OrderByDescending(u => u.Name)
    .ToPagedListAsync(page: 1, pageSize: 20);

var first = await pgLib.Query<User>()
    .Where(u => u.Id == 1)
    .FirstOrDefaultAsync();

var total   = await pgLib.Query<User>().Where(u => u.IsActive).CountAsync();
var maxId   = await pgLib.Query<User>().MaxAsync(u => u.Id);
var sum     = await pgLib.Query<User>().SumAsync(u => u.Credits);
var average = await pgLib.Query<User>().AverageAsync(u => u.Credits);

// Bulk update / delete
await pgLib.Query<User>()
    .Where(u => !u.IsActive)
    .UpdateAsync(new() { ["Status"] = "archived" });

await pgLib.Query<User>().Where(u => !u.IsActive).DeleteAsync();

Chain methods: Where, OrderBy/OrderByDescending, Limit/Offset (aliases Take/Skip), Join(table, condition, JoinType), Select(...), GroupBy(...), WithConnection(id). Terminal methods: ToListAsync, FirstOrDefaultAsync, ToPagedListAsync, CountAsync, MaxAsync/MinAsync/SumAsync/AverageAsync, UpdateAsync, DeleteAsync.

Raw SQL

var raw = pgLib.QueryRaw();
var rows = await raw.QueryAsync(
    "SELECT \"Name\" FROM \"users\" WHERE \"Id\" = @id",
    new() { ["@id"] = 1 });           // Result<List<Dictionary<string, object?>>>

await raw.ExecuteAsync("TRUNCATE \"users\"");   // Result<int>

Transactions

await using var tx = await pgLib.BeginTransactionAsync();   // optional connectionId
try
{
    // ... work on the same connection/transaction ...
    await tx.CommitAsync();
}
catch
{
    await tx.RollbackAsync();
}
// If neither Commit nor Rollback is called, dispose auto-rolls back.

Table Sync and Migrations

// Single entity (creates table if missing, otherwise adds missing columns/indexes)
Result<SyncResult> result = await pgLib.SyncTableAsync<User>();      // createBackup: true by default

// Lower-level service for batch operations
await pgLib.TableSync.SyncTablesAsync(new[] { typeof(User), typeof(Order) });
await pgLib.TableSync.SyncNamespaceAsync("MyApp.Entities", includeDerivedNamespaces: true);

SyncResult reports Success, SchemaName/TableName, the list of Operations applied, any Errors, and Duration.

Before altering an existing table, a timestamped schema backup is written under the library's data directory (backups/). Manage backups via pgLib.BackupManager:

await pgLib.BackupManager.BackupTableSchemaAsync("public", "users");
await pgLib.BackupManager.CleanupOldBackupsAsync(keepCount: 10);

Applied migrations are tracked in migrations/migration_history.json via pgLib.MigrationTracker (RecordMigrationAsync, HasMigrationBeenAppliedAsync, GetAppliedMigrationsAsync, RemoveMigrationRecordAsync).

Configuration

Config file: config.postgresql.json

{
  "Databases": {
    "Default": {
      "Enabled": true,
      "Host": "localhost",
      "Port": 5432,
      "Database": "mydb",
      "Username": "postgres",
      "Password": "",
      "ConnectionTimeout": 30,
      "CommandTimeout": 30,
      "MinPoolSize": 5,
      "MaxPoolSize": 100,
      "MaxIdleTime": 60,
      "SslMode": "Prefer",
      "AllowDestructiveSync": false,
      "SlowQueryThresholdMs": 1000
    }
  }
}
  • Databases — a named map; add more keys (e.g. "Reporting") and pass that key as connectionId. Disabled databases ("Enabled": false) are skipped at startup.
  • SslModeDisable, Allow, Prefer, Require, VerifyCA, or VerifyFull.
  • MaxIdleTime — seconds an idle pooled connection is kept before being closed.
  • AllowDestructiveSync — dev-only; allows DROP operations during schema sync.
  • SlowQueryThresholdMs — queries at or above this duration are logged as warnings.

You can also register a database at runtime:

pgLib.RegisterDatabase("Reporting", new DatabaseConfig
{
    Host = "reports.internal", Database = "analytics",
    Username = "reader", Password = "***"
});

Documentation

Full API docs: https://github.com/Media2A/CodeLogic.Libs

Requirements

License

MIT — see LICENSE

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
4.6.72 43 6/20/2026
4.6.69-preview 32 6/20/2026
4.5.2 105 5/24/2026
4.5.2-preview.68 61 6/20/2026
4.5.1 104 5/24/2026
4.5.1-preview.56 54 5/24/2026
4.4.2-preview.53 62 5/24/2026
4.4.1 102 5/24/2026
4.0.5 101 5/15/2026
4.0.4 110 5/9/2026
4.0.3 111 5/9/2026
3.3.1 112 4/18/2026
3.3.0 116 4/18/2026
3.2.11 106 4/18/2026
3.2.10 108 4/18/2026
3.2.9 106 4/18/2026
3.2.8 106 4/18/2026
3.2.7 101 4/18/2026
3.2.6 102 4/18/2026
3.2.5 107 4/18/2026
Loading failed

# CL.PostgreSQL — Changelog

All notable changes to **CodeLogic.PostgreSQL** are documented here. Versions follow
[Semantic Versioning](https://semver.org/).

## [4.5.2] — 2026-06-20

### Documentation

- Documented the full **query builder** surface: `OrderByDescending`, `Limit`/`Offset`
 (and `Take`/`Skip` aliases), `Join`, `Select`, `GroupBy`, `WithConnection`,
 `ToPagedListAsync`, `FirstOrDefaultAsync`, the `CountAsync`/`MaxAsync`/`MinAsync`/
 `SumAsync`/`AverageAsync` aggregates, and bulk `UpdateAsync`/`DeleteAsync`. Earlier
 docs listed only `Where`/`OrderBy`/`ToListAsync`.
- Documented raw SQL access via `QueryRaw()` (`QueryAsync`/`ExecuteAsync`).
- Documented the **repository** beyond basic CRUD: `InsertManyAsync`, `GetByColumnAsync`,
 `GetPagedAsync`, `FindAsync`, `IncrementAsync`/`DecrementAsync`, and
 `RawQueryAsync`/`RawExecuteAsync`.
- Documented the schema attributes `[Table]`, `[Column]`, `[ForeignKey]`,
 `[CompositeIndex]`, and `[Ignore]`, plus the `DataType` enum.
- Documented **table sync / migrations**: `SyncTablesAsync`, `SyncNamespaceAsync`,
 `SyncResult`, the `BackupManager` (schema backups + cleanup), and the
 `MigrationTracker` JSON history.
- Documented **transactions** via `BeginTransactionAsync` (auto-rollback on dispose).
- Documented previously-omitted configuration: `MaxIdleTime`, `AllowDestructiveSync`,
 multi-database `connectionId` selection, and runtime `RegisterDatabase`.

### Notes

- The 4.0.0 "repository CRUD only" note is superseded — the query builder
 (joins, aggregation, paging, bulk update/delete) is present and now documented.

## [4.5.0] — 2026-05-24

### Changed

- **Unified versioning.** All CodeLogic.Libs now share a single version line
 controlled by `version.txt` in the repo root. This is a version alignment
 release — no functional changes to this library.
## [4.0.4] — 2026-04-16

### Changed

- README + manifest refresh for the v4 baseline. No functional changes vs 4.0.3.
- `LibraryManifest.Version` now reads from assembly metadata.

## [4.0.2] — 2026-04-09

### Changed

- Annotated PostgreSQL configuration with `[ConfigField]` for the admin UI surface.
- Aligned with the v4 baseline across all libraries.

## [4.0.0] — 2026-04-09

Major rewrite. Republished as v4.0.0 to reset the version line under the
unified v4 baseline. Repository pattern + attribute-driven schema sync,
mirroring the CL.MySQL2 surface.

### Notes

- The MySQL2 4.0 query-builder rewrite (projection pushdown, SQL aggregation,
 smart-cache pools) has not been ported to CL.PostgreSQL yet — repository
 CRUD only.
- Earlier history is retained in the
 [git log](https://github.com/Media2A/CodeLogic.Libs/commits/main/CL.PostgreSQL).