| .github/workflows | ||
| .vscode | ||
| src | ||
| utils | ||
| .editorconfig | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| LICENSE.md | ||
| README.md | ||
MaksIT.Persistence
NuGet facade over linq2db + PostgreSQL for ASP.NET Core Engines: connection factory, FluentMigrator startup, and MaksIT.Results guards.
Table of Contents
- Overview
- Result conventions
- Getting Started
- Installation
- Registering services
- What stays in the product
- Contributing
- Contact
- License
Overview
MaksIT.Persistence wraps linq2db PostgreSQL wiring so Engine code depends on ILinq2DbConnectionFactory instead of copying DataOptions / ProviderName.PostgreSQL / startup wait in every product. Domain tables, Dto, FluentMapping content, and FluentMigrator migration classes stay in the product Engine.
Linq2Db queries stay in the product: persist/query services still call GetTable<T>(). This library hides connection lifetime, Postgres transients, and FluentMigrator bootstrap.
| Need | Register | Inject |
|---|---|---|
Scoped DataConnection |
RegisterLinq2Db(connectionString, mappingSchema?) |
ILinq2DbConnectionFactory |
| FluentMigrator wait / create-DB / retry MigrateUp | RegisterPostgresMigrations(connectionString, assembly, options?) |
IRunMigrationsService |
Work leases are not in this package: use MaksIT.Dapr (RegisterWorkLeases) for most first-party apps, or MaksIT.HAMode for maksit-buoy only.
Result conventions
- Success / failure: check
result.IsSuccess. Map to HTTP withresult.ToActionResult(). - Cancellation:
Linq2DbGuardrethrowsOperationCanceledException(do not wrap as a failedResult). - Unique violation (
23505):Linq2DbGuardmaps toConflict. - Missing row: product persist/query ports return
NotFound— not this library.
Getting Started
Ensure that you have the following installed:
- .NET 10 SDK
- Docker (optional; used by RepoUtils Linux test validation)
Installation
dotnet add package MaksIT.Persistence
Or in your .csproj:
<PackageReference Include="MaksIT.Persistence" Version="2.0.1" />
Registering services
Call from the product Engine Add*Engine, not from host JSON binding. Pass the Engine connection string; optional MappingSchema for fluent maps (omit to use attribute mapping).
using MaksIT.Persistence.Extensions;
services.RegisterLinq2Db(config.ConnectionString, ProductLinq2DbMapping.Schema);
services.RegisterPostgresMigrations(
config.ConnectionString,
typeof(BaselineSchema).Assembly,
new PostgresMigrationOptions {
EnsureCoordinationTables = ct => CoordinationTableProvisioner.EnsureAsync(config.ConnectionString, ct),
VerifySchema = ct => VerifyCoreSchemaAsync(config.ConnectionString, ct),
});
Schema changes go in a new FluentMigrator [Migration] (Create.Table / Alter.Table.AddColumn; Drop/rename needs a separate decision). Host Program.cs before RunAsync:
await app.Services.EnsureLinq2DbMigratedAsync();
Product persist/query:
using var db = connectionFactory.Create();
var row = db.GetTable<UserDto>().FirstOrDefault(u => u.Id == id);
What stays in the product
- Table names, Dto, FluentMapping entity list, FluentMigrator
[Migration]classes - Coordination DDL unique to the product (hook on
PostgresMigrationOptions) I*PersistenceService/I*QueryServiceand domain services- HA work leases (Dapr or HAMode)
Contributing
See CONTRIBUTING.md.
Contact
For questions or support, contact:
- Email: maksym.sadovnychyy@gmail.com
License
This project is licensed under the MIT License. See the LICENSE.md file for details.