ArturRios.Data β a modular data-access toolkit for .NET. One consistent, envelope-based repository
style across relational databases (EF Core over PostgreSQL / MySQL / SQLite, plus a Dapper read
path) and NoSQL stores (MongoDB, DynamoDB), plus file export writers (CSV, JSON, TXT,
MessagePack, Excel). Every operation returns a
DataOutput / ProcessOutput envelope, so
infrastructure failures β including optimistic-concurrency conflicts β surface as errors on the result
instead of unhandled exceptions.
- π Full documentation: https://artur-rios.github.io/dotnet-data
- π§© Architecture & diagrams: Architecture
- ποΈ Guides: Relational Β· MongoDB Β· DynamoDB
Each backend is a separate NuGet package so you install only what you use. The relational packages
share a common core; the NoSQL and export packages are standalone. Everything depends on
ArturRios.Output for the result envelopes.
flowchart TB
Output["ArturRios.Output<br/><i>DataOutput / ProcessOutput envelopes</i>"]
subgraph Relational["Relational stack β EF Core"]
direction TB
Core["ArturRios.Data.Relational.Core<br/><i>repository & unit-of-work abstractions,<br/>EfRepository, BaseDbContext, provider seam</i>"]
Sqlite["ArturRios.Data.Sqlite"]
Postgres["ArturRios.Data.PostgreSql"]
MySql["ArturRios.Data.MySql<br/><i>(deferred)</i>"]
Dapper["ArturRios.Data.Dapper<br/><i>read-only raw SQL</i>"]
end
subgraph NoSQL["NoSQL stores β standalone"]
direction TB
Mongo["ArturRios.Data.MongoDb"]
Dynamo["ArturRios.Data.DynamoDb"]
end
subgraph Export["File export β standalone"]
direction TB
ExportCore["ArturRios.Data.Export<br/><i>CSV, JSON, TXT, MessagePack</i>"]
ExportExcel["ArturRios.Data.Export.Excel<br/><i>.xlsx add-on</i>"]
end
Sqlite --> Core
Postgres --> Core
MySql --> Core
Dapper --> Core
Core --> Output
Mongo --> Output
Dynamo --> Output
ExportExcel --> ExportCore
ExportCore --> Output
| Package | Backend | Depends on | Status |
|---|---|---|---|
ArturRios.Data.Relational.Core |
EF Core abstractions (shared) | ArturRios.Output, EF Core |
β |
ArturRios.Data.Sqlite |
SQLite | Relational.Core | β |
ArturRios.Data.PostgreSql |
PostgreSQL (Npgsql) | Relational.Core | β |
ArturRios.Data.MySql |
MySQL (Pomelo) | Relational.Core | β³ deferredΒΉ |
ArturRios.Data.Dapper |
Raw-SQL reads over the EF connection | Relational.Core, Dapper | β |
ArturRios.Data.MongoDb |
MongoDB document store | ArturRios.Output, MongoDB.Driver |
β |
ArturRios.Data.DynamoDb |
AWS DynamoDB | ArturRios.Output, AWSSDK.DynamoDBv2 |
β |
ArturRios.Data.Export |
CSV / JSON / TXT / MessagePack writers | ArturRios.Output, MessagePack |
β |
ArturRios.Data.Export.Excel |
Excel .xlsx export add-on | Export, ClosedXML | β |
ΒΉ Deferred until Pomelo.EntityFrameworkCore.MySql publishes an EF Core 10 release (its latest still
targets EF Core 9). Source is written and excluded from the build. See
Relational β MySQL.
Install the package(s) for your backend with the .NET CLI (or the NuGet Package Manager in Visual Studio):
# Relational (EF Core) β the core + a provider matching your engine:
dotnet add package ArturRios.Data.Relational.Core
dotnet add package ArturRios.Data.Sqlite # or .PostgreSql
# Optional raw-SQL read path (relational):
dotnet add package ArturRios.Data.Dapper
# NoSQL (standalone β no core needed):
dotnet add package ArturRios.Data.MongoDb
dotnet add package ArturRios.Data.DynamoDb
# File export (standalone β no core needed):
dotnet add package ArturRios.Data.Export
dotnet add package ArturRios.Data.Export.Excel # optional β adds ExportFormat.ExcelRequires .NET 10.0 or later.
Every read/write method returns a DataOutput<T> (data + success/errors) or, for operations with no
payload (deletes, transactions), a ProcessOutput. You inspect Success / Data / Errors instead of
catching exceptions.
classDiagram
class ProcessOutput {
+bool Success
+List~string~ Errors
+List~string~ Messages
}
class DataOutput~T~ {
+T Data
}
ProcessOutput <|-- DataOutput
1. Define an entity (ArturRios.Data.Relational.Core):
using ArturRios.Data.Relational.Core;
public class Product : Entity // or : VersionedEntity for optimistic concurrency
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}2. Define a context deriving from BaseDbContext:
using ArturRios.Data.Relational.Core.Configuration;
using Microsoft.EntityFrameworkCore;
public class AppDbContext(DbContextOptions options) : BaseDbContext(options)
{
public DbSet<Product> Products => Set<Product>();
}3. Configure (appsettings.json, default section "ArturRios.Data.Core"):
{
"ArturRios.Data.Core": {
"DatabaseType": "PostgreSql",
"ConnectionString": "Host=localhost;Database=mydb;Username=app;Password=secret;"
}
}4. Register the provider + the data layer (Program.cs):
using ArturRios.Data.PostgreSql; // brings AddPostgreSqlProvider()
using ArturRios.Data.Relational.Core.DependencyInjection;
builder.Services.AddPostgreSqlProvider();
builder.Services.AddDataConfigFromSettings<AppDbContext>(builder.Configuration, "ArturRios.Data.Core");5. Inject and use the enveloped repository / unit of work:
using ArturRios.Data.Relational.Core.Interfaces;
using ArturRios.Data.Relational.Core.Transactions;
using ArturRios.Output;
public class ProductService(IAsyncRepository<Product> repo, IAsyncUnitOfWork unitOfWork)
{
public async Task<int> CreateAsync(Product p)
{
DataOutput<int> result = await repo.CreateAsync(p);
return result.Success ? result.Data : throw new InvalidOperationException(string.Join(", ", result.Errors));
}
public Task<DataOutput<int>> CreateTwoAtomicallyAsync(Product a, Product b) =>
unitOfWork.ExecuteInTransactionAsync(async () =>
{
var first = await repo.CreateAsync(a);
await repo.CreateAsync(b);
return first.Data;
});
}The full relational guide (providers, sync + async interfaces, the Query() escape hatch, concurrency,
transactions, and the Dapper read path) is at
Relational.
classDiagram
class Entity { +long Id }
class VersionedEntity { +Guid ConcurrencyStamp }
Entity <|-- VersionedEntity
class IReadOnlyRepository~T~ {
+Query() IQueryable~T~
+GetAll() DataOutput
+GetById(long) DataOutput
}
class IRepository~T~ {
+Create(T) DataOutput
+Update(T) DataOutput
+Delete(T) DataOutput
}
class IAsyncReadOnlyRepository~T~
class IAsyncRepository~T~
class EfRepository~T~
IReadOnlyRepository <|-- IRepository
IAsyncReadOnlyRepository <|-- IAsyncRepository
IRepository <|.. EfRepository
IAsyncRepository <|.. EfRepository
class IUnitOfWork
class IAsyncUnitOfWork
class EfUnitOfWork
IUnitOfWork <|.. EfUnitOfWork
IAsyncUnitOfWork <|.. EfUnitOfWork
The NoSQL packages are standalone (no relational core) but keep the same enveloped style.
- MongoDB β a document repository (
IAsyncDocumentRepository<T>) withDocument/VersionedDocumentidentity,Find(predicate)server-side filtering, aQuery()LINQ escape hatch, opt-in optimistic concurrency, and multi-document transactions (IMongoUnitOfWork, requires a replica set). β MongoDB guide - DynamoDB β an async-only repository (
IAsyncDynamoRepository<T>) over the AWS object-persistence model with POCO-attribute keys,[DynamoDBVersion]optimistic concurrency, Query/Scan/batch, and aServiceUrlfor DynamoDB Local / LocalStack. β DynamoDB guide
| Page | What's there |
|---|---|
| Architecture | Package diagram, class diagrams, the envelope model, design principles |
| Relational | EF Core setup, providers, repositories, unit of work, concurrency, Dapper |
| MongoDB | Documents, repository, transactions, concurrency |
| DynamoDB | Item POCOs, repository, query/scan/batch, concurrency |
Semantic Versioning (SemVer). Breaking changes bump the major version; new non-breaking behavior bumps the minor; fixes bump the patch.
Use the official .NET CLI to build, test and publish, and Git for source control. Optional helper toolsets: Dotnet Tools Β· Python Dotnet Tools.
Licensed under the MIT License β see LICENSE.