MonadicSharp.Persistence
1.0.0
dotnet add package MonadicSharp.Persistence --version 1.0.0
NuGet\Install-Package MonadicSharp.Persistence -Version 1.0.0
<PackageReference Include="MonadicSharp.Persistence" Version="1.0.0" />
<PackageVersion Include="MonadicSharp.Persistence" Version="1.0.0" />
<PackageReference Include="MonadicSharp.Persistence" />
paket add MonadicSharp.Persistence --version 1.0.0
#r "nuget: MonadicSharp.Persistence, 1.0.0"
#:package MonadicSharp.Persistence@1.0.0
#addin nuget:?package=MonadicSharp.Persistence&version=1.0.0
#tool nuget:?package=MonadicSharp.Persistence&version=1.0.0
MonadicSharp.Persistence
Result-aware repository and Unit of Work for EF Core 8 — NotFound, Conflict, and DatabaseError are typed
Result<T>values, never null or unhandled exceptions.
Overview
MonadicSharp.Persistence brings Railway-Oriented Programming to the data access layer:
IRepository<T, TId>— full read-write repository, all methods returnResult<T>IReadRepository<T, TId>— read-only projection for CQRS-style separationIUnitOfWork—SaveChangesAsyncreturnsResult<int>, concurrency conflicts are typed errorsEfCoreRepository<T, TId>— EF Core 8 implementationEfCoreUnitOfWork— supports transactions viaBeginTransactionAsync/CommitTransactionAsyncQueryableExtensions—.ToResultAsync(),.FirstOrDefaultResultAsync(),.SingleResultAsync()for inline LINQPersistenceError— typed error factory for all persistence failure scenarios
Installation
dotnet add package MonadicSharp.Persistence
dotnet add package Microsoft.EntityFrameworkCore.SqlServer # or Npgsql, Sqlite, etc.
Quick Start
1. Define your DbContext as usual
public class AppDbContext : DbContext
{
public DbSet<Order> Orders => Set<Order>();
// ...
}
2. Register in DI
services.AddDbContext<AppDbContext>(opts =>
opts.UseNpgsql(connectionString));
services
.AddMonadicSharpPersistence<AppDbContext>() // registers IUnitOfWork
.AddMonadicSharpRepository<Order, Guid>(); // registers IRepository<Order, Guid>
3. Use in your services
public class OrderService(IRepository<Order, Guid> orders, IUnitOfWork uow)
{
public async Task<Result<Order>> PlaceOrderAsync(CreateOrderDto dto)
{
var order = new Order(dto.CustomerId, dto.Items);
var addResult = await orders.AddAsync(order);
if (addResult.IsFailure) return addResult;
var saveResult = await uow.SaveChangesAsync();
return saveResult.IsSuccess
? Result<Order>.Success(order)
: Result<Order>.Failure(saveResult.Error);
}
public async Task<Result<Order>> GetOrderAsync(Guid id) =>
await orders.FindAsync(id);
// Returns PersistenceError.NotFound if missing — no null checks needed
}
IRepository API
// Read
Task<Result<T>> FindAsync(TId id, ct)
Task<Result<T>> FirstOrDefaultAsync(predicate, ct)
Task<Result<IReadOnlyList<T>>> ListAsync(predicate?, ct)
Task<Result<bool>> AnyAsync(predicate, ct)
Task<Result<int>> CountAsync(predicate?, ct)
// Write (changes not persisted until SaveChangesAsync)
Task<Result<T>> AddAsync(T entity, ct)
Task<Result<Unit>> AddRangeAsync(IEnumerable<T> entities, ct)
Result<T> Update(T entity)
Task<Result<Unit>> DeleteAsync(TId id, ct)
Result<Unit> Delete(T entity)
IUnitOfWork API
Task<Result<int>> SaveChangesAsync(ct) // persists all pending changes
Task<Result<Unit>> BeginTransactionAsync(ct)
Task<Result<Unit>> CommitTransactionAsync(ct)
Task<Result<Unit>> RollbackTransactionAsync(ct)
Transaction example
await uow.BeginTransactionAsync();
var addOrder = await orders.AddAsync(order);
var debitStock = await inventory.UpdateAsync(item);
if (addOrder.IsFailure || debitStock.IsFailure)
{
await uow.RollbackTransactionAsync();
return Result<Unit>.Failure(addOrder.Error ?? debitStock.Error!);
}
await uow.SaveChangesAsync();
await uow.CommitTransactionAsync();
QueryableExtensions
For custom queries that go beyond the repository interface:
var recentOrders = await dbContext.Orders
.Where(o => o.CreatedAt > DateTime.UtcNow.AddDays(-7))
.OrderByDescending(o => o.CreatedAt)
.ToResultAsync(ct);
// Single entity
var order = await dbContext.Orders
.SingleResultAsync(o => o.ExternalRef == externalId, ct);
// Returns PersistenceError.NotFound or PersistenceError.TooManyResults
// First or not-found
var latest = await dbContext.Orders
.OrderByDescending(o => o.CreatedAt)
.FirstOrDefaultResultAsync(ct);
Error Codes
| Code | Meaning |
|---|---|
PERSISTENCE_NOT_FOUND |
Entity with the given id/predicate does not exist |
PERSISTENCE_CONFLICT |
Entity with the same key already exists |
PERSISTENCE_CONCURRENCY_CONFLICT |
DbUpdateConcurrencyException — row was modified by another process |
PERSISTENCE_DATABASE_ERROR |
Unexpected database exception |
PERSISTENCE_TOO_MANY_RESULTS |
SingleResultAsync found more than one match |
PERSISTENCE_TRANSACTION_ALREADY_ACTIVE |
BeginTransactionAsync called twice |
PERSISTENCE_NO_ACTIVE_TRANSACTION |
Commit/Rollback without Begin |
License
MIT — part of MonadicSharp.Framework.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net8.0
- Microsoft.EntityFrameworkCore (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- MonadicSharp (>= 1.4.0)
- MonadicSharp.Agents (>= 1.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on MonadicSharp.Persistence:
| Package | Downloads |
|---|---|
|
MonadicSharp.Framework
Meta-package for the MonadicSharp Framework — install this single package to get Agents, Caching, Http, Persistence, Security, and Telemetry in one shot. For à-la-carte usage, reference individual MonadicSharp.* packages instead. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 39 | 3/3/2026 |