AxisRepository 2.0.1
See the version list below for details.
dotnet add package AxisRepository --version 2.0.1
NuGet\Install-Package AxisRepository -Version 2.0.1
<PackageReference Include="AxisRepository" Version="2.0.1" />
<PackageVersion Include="AxisRepository" Version="2.0.1" />
<PackageReference Include="AxisRepository" />
paket add AxisRepository --version 2.0.1
#r "nuget: AxisRepository, 2.0.1"
#:package AxisRepository@2.0.1
#addin nuget:?package=AxisRepository&version=2.0.1
#tool nuget:?package=AxisRepository&version=2.0.1
AxisRepository — Documentation
A unit-of-work abstraction with AxisResult baked in — IAxisUnitOfWork with three primitives (StartAsync, SaveChangesAsync, RollbackAsync) and a default-interface InTransactionAsync(work) that orchestrates them. The bundled AxisRepository.Postgres and AxisRepository.MySql adapters ship a typed command builder, retry on transient errors, conflict detection on unique-constraint violations, and a keyed-DI provider for multi-database setups.
public Task<AxisResult<CreatePersonResponse>> HandleAsync(CreatePersonCommand cmd)
=> uow.InTransactionAsync(() =>
factory.CreateAsync(cmd)
.ThenAsync(person => writer.CreateAsync(person))
.MapAsync(_ => new CreatePersonResponse { PersonId = cmd.PersonId }));
Use this page as a map: read the trunk below (~5 min) and jump straight to the detail of the group you need — without reading hundreds of lines.
The trunk (read first)
The interface in 60 seconds
public interface IAxisUnitOfWork : IDisposable, IAsyncDisposable
{
Task<AxisResult> StartAsync();
Task<AxisResult> SaveChangesAsync();
Task<AxisResult> RollbackAsync();
Task<AxisResult> InTransactionAsync(Func<Task<AxisResult>> work);
Task<AxisResult<T>> InTransactionAsync<T>(Func<Task<AxisResult<T>>> work);
}
StartAsync opens a transaction; SaveChangesAsync commits; RollbackAsync rolls back. The two InTransactionAsync defaults wrap the three primitives — start, run the work, commit on success, roll back on failure or exception (and re-throw the exception). → The IAxisUnitOfWork contract
Why a Result-aware unit of work?
A failed business step inside a transaction usually means roll back — but a try/catch is not the right test, because failure here is a value (AxisResult.IsFailure), not an exception. InTransactionAsync reads the result and decides: commit on Ok, rollback on Error, rethrow on a raw exception. → InTransactionAsync — the right transaction wrapper
Bundled adapters — PostgreSQL and MySQL
AxisRepository.Postgres ships:
PostgresUnitOfWork— implementsIAxisUnitOfWorkviaNpgsqlConnection+NpgsqlTransaction, traces every operation throughIAxisTelemetry.IPostgresUnitOfWork—IAxisUnitOfWork+NewCommandAsync(sql)for raw SQL.PostgresDbRepository— the ready-madeIAxisDbRepositoryexecutor your repositories compose:ExecuteAsync/ExecuteCountAsync/GetAsync/ListAsyncwith parameter binding, retries on transientSqlStatecodes, and unique-key violations converted intoAxisError.Conflict.PostgresRepositoryBase— the machinery under the executor, also available as an inheritance surface for a repository deliberately bound to the dialect.
services.AddPostgresUnitOfWork(serviceKey: "main", connectionString: "Host=…");
services.AddPostgresDbRepository(serviceKey: "main");
AxisRepository.MySql ships the same shape over MySqlConnector — MySqlUnitOfWork, IMySqlUnitOfWork, MySqlDbRepository, MySqlRepositoryBase — sharing the retry/fault machinery with Postgres through AxisRepositoryBase:
services.AddMySqlUnitOfWork(serviceKey: "main", connectionString: "Server=…");
services.AddMySqlDbRepository(serviceKey: "main");
→ Postgres adapter · MySQL adapter · Repository base · Keyed multi-database
Schema DDL and migrations
A table is declared once, dialect-agnostic, with the fluent AxisTable builder (Axis.Ddl); an injected IAxisSqlDialect renders it into concrete Postgres or MySQL DDL:
public static AxisTable Define() => new AxisTable("AXIS_CACHE.CACHE_ENTRIES")
.Column("CACHE_KEY", AxisDbType.Varchar(200), primaryKey: true)
.Column("VALUE_JSON", AxisDbType.Json, notNull: true)
.Index("IDX_CACHE_ENTRIES_EXPIRES_AT", "EXPIRES_AT");
IAxisMigrationRunner then applies the rendered script to a schema idempotently — bootstrapping the schema and a MIGRATIONS control table, serializing concurrent instances with a schema-scoped lock, and skipping versions already recorded.
→ Schema DDL · Migrations
Installation
dotnet add package AxisRepository # the abstraction
dotnet add package AxisRepository.Postgres # the Postgres adapter (Npgsql)
dotnet add package AxisRepository.MySql # the MySQL adapter (MySqlConnector)
→ Full guide: Getting started
The map (jump to what you need)
| Group | You want to… | Detail |
|---|---|---|
Contract · IAxisUnitOfWork |
the three primitives + the wrapper | iaxisunitofwork.md |
InTransactionAsync ⭐ |
wrap a railway in a transaction | in-transaction.md |
Postgres · IPostgresUnitOfWork |
the bundled NpgsqlCommand builder |
postgres-adapter.md |
MySQL · IMySqlUnitOfWork |
the bundled MySqlCommand builder |
mysql-adapter.md |
| Repository base | the IAxisDbRepository executor your repositories compose, and the PostgresRepositoryBase/MySqlRepositoryBase machinery underneath |
repository-base.md |
Schema DDL · AxisTable |
declare a table once, dialect-agnostic | ddl.md |
Migrations · IAxisMigrationRunner |
apply DDL to a schema, idempotently | migrations.md |
| Multi-database | keyed DI for two or more databases | keyed-multi-database.md |
| Custom adapter | implement IAxisUnitOfWork for another store |
custom-adapter.md |
| Why? | the case against EF Core's DbContext |
why-axisrepository.md |
| Reference | every member at a glance | api-reference.md |
Start here: Getting started · The IAxisUnitOfWork contract · Why AxisRepository?
Fundamentals: InTransactionAsync · Postgres adapter · MySQL adapter · Repository base
Reference & extras: Schema DDL · Migrations · Keyed multi-database · Custom adapter · API reference
Design principles
- Transactions follow the rail. A failed
AxisResultrolls back; a successful one commits; an exception rolls back and rethrows. - Errors are typed. Unique-key violations →
Conflict. Connection failures →InternalServerError. NotFound →NotFound. No string-matching at call sites. - Transient errors retry transparently. The repository base retries on Postgres
SqlState40001 / 40P01 / 08006 / 08003 / 08001 / 57P03 (and the equivalent MySQL deadlock/lock-wait-timeout/connection-blip conditions) with backoff. - No
DbContextsmell. Repositories speak SQL or ports, the unit of work owns the connection and the transaction. No proxies, no change tracking magic. - Cancellation flows through
IAxisMediator. Every operation readsmediator.CancellationToken— no extra parameters in the contract. - Schema is declared once, rendered per dialect. An
AxisTableis dialect-agnostic;IAxisSqlDialectrenders it,IAxisMigrationRunnerapplies it idempotently. One definition can never drift between Postgres and MySQL because there is only one place to edit.
License
Apache 2.0
| 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
- AxisMediator.Contracts (>= 2.0.1)
- AxisResult (>= 2.0.1)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on AxisRepository:
| Package | Downloads |
|---|---|
|
AxisSaga
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisCache.Repository
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisRepository.MySql
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisRepository.Postgres
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisBus.Repository
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.0 | 388 | 7/21/2026 |
| 2.1.1 | 223 | 7/17/2026 |
| 2.0.2-local | 230 | 7/17/2026 |
| 2.0.1 | 239 | 7/15/2026 |
| 2.0.0 | 250 | 7/15/2026 |