Forge.Repository
A production-grade, database-agnostic repository pattern for .NET 10.
Forge.Repository provides a clean, consistent data-access API that works identically across SQL Server, PostgreSQL, Oracle, MySQL, and MariaDB. Install the core package, add one provider package, register in DI - and your repository, unit of work, audit trail, and criteria pattern are ready to use.
dotnet add package Forge.Repository
dotnet add package Forge.Repository.SqlServer # or PostgreSql / Oracle / MySqlWhy Forge.Repository?
Most projects end up with the same boilerplate: a generic IRepository<T>, a unit of work wrapper, some audit fields on base models, and a handful of raw SQL escape hatches. Forge.Repository packages all of that into a single, tested, NuGet-published library so you stop copying it between solutions.
| Pain point | What Forge provides |
|---|---|
| Repeated CRUD boilerplate | IRepositoryAsync<T> with full async CRUD, bulk ops, predicates |
| Switching databases | Swap one AddForge* call - zero application code changes |
| Complex query logic scattered in services | Criteria pattern - queries in dedicated, testable objects |
| Manual audit timestamps | IAuditableBaseModel with OnCreate / OnUpdate / OnDelete hooks |
| ORM limitations | FindAllBySql, ExecuteSqlRaw with full async and cancellation |
| Transaction coordination | IUnitOfWork.SaveChangesAsync commits all repositories at once |
Package Ecosystem
Forge.Repository is split into a core package and provider packages. Install the core package first, then add exactly one provider:
| Package | Purpose |
|---|---|
Forge.Repository | Core interfaces, base models, criteria, unit of work - always required |
Forge.Repository.SqlServer | Microsoft SQL Server via Microsoft.EntityFrameworkCore.SqlServer |
Forge.Repository.PostgreSql | PostgreSQL via Npgsql.EntityFrameworkCore.PostgreSQL |
Forge.Repository.Oracle | Oracle via Oracle.EntityFrameworkCore |
Forge.Repository.MySql | MySQL and MariaDB via Pomelo.EntityFrameworkCore.MySql |
Always use the same version for Forge.Repository and your provider package. Mixed versions will cause runtime errors.
At a Glance
// 1. Register — Program.cs
builder.Services.AddForgeRepositorySqlServer<AppDbContext>(
connectionString: builder.Configuration.GetConnectionString("ConnectionString")!,
poolingOptions: new ForgeDbContextPoolingOptions { EnablePooling = true, MinPoolSize = 5, MaxPoolSize = 20 },
configure: tuner => { tuner.SetRetry(3).SetTimeout(30).EnableLazyLoading(); });
// 2. Define your entity
public class Order : IAuditableBaseModel
{
public string Id { get; set; } = Ulid.NewUlid().ToString();
public string CustomerId { get; set; } = string.Empty;
public decimal Total { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; } = string.Empty;
public string ModifiedBy { get; set; } = string.Empty;
public bool IsDeleted { get; set; }
public void OnCreate() => CreatedOn = DateTime.UtcNow;
public void OnUpdate() => ModifiedOn = DateTime.UtcNow;
public void OnDelete() => IsDeleted = true;
}
// 3. Use in a service
public class OrderService(IUnitOfWork uow)
{
private readonly IRepositoryAsync<Order> _orders = uow.GetRepositoryAsync<Order>();
public Task<IList<Order>> GetAllAsync(CancellationToken ct) => _orders.GetAllAsync(ct);
public Task<Order> GetAsync(string id, CancellationToken ct) => _orders.GetByIdAsync(id, ct);
public async Task PlaceAsync(Order order, CancellationToken ct)
{
await _orders.AddAsync(order, ct);
await uow.SaveChangesAsync(ct);
}
}Quick Navigation
Source & Issues
Forge.Repository is closed source - the compiled packages are published to NuGet.org under a proprietary license. Source will open soon.
- 🐛 Bug reports & feature requests → GitHub Issues
- 💬 Questions & discussion → GitHub Discussions
- 📋 Changelog → sayem.xyz/forge-repository/changelog
- 📦 NuGet → nuget.org/packages/Forge.Repository