Skip to content

CaeriusNET/CaeriusNet

CaeriusNet

NuGet version NuGet downloads .NET 10 C# 14 SQL Server 2019+ MIT License

Overview

CaeriusNet is a high-performance micro-ORM for C# 14 and .NET 10, built exclusively around SQL Server stored procedures. It eliminates boilerplate data-access code through compile-time source generators, delivers multiple caching strategies out of the box, and supports multi-result-set queries — all in a single NuGet package.


Project Structure

Directory Description
Src/ Core library — CaeriusNet NuGet package source
SourceGenerators/ Roslyn incremental source generators and analyzers used by the package
Tests/ Unit tests, generator tests, integration tests
Benchmark/ BenchmarkDotNet performance benchmarks
Exemples/ Example projects (Aspire + Console); directory name retained for compatibility
Documentations/ VitePress documentation site

Why CaeriusNet?

  • Zero reflection at runtime — DTO and TVP mappers are generated at compile time via Roslyn source generators.
  • Stored procedures first — every query is a stored procedure call; no inline SQL, no query builders.
  • Three caching layers — Frozen (immutable in-process), In-Memory (TTL), and Redis (distributed).
  • Multi-result sets — retrieve up to 5 strongly-typed result sets in a single database round-trip.
  • TVP support — pass structured data to SQL Server efficiently without any DataTable overhead.
  • AutoContracts — optionally pull and verify stored procedure contracts during dotnet build from the same NuGet package.
  • Aspire-ready — first-class integration with .NET Aspire for cloud-native scenarios.

Installation

dotnet add package CaeriusNet

The runtime, analyzers, source generators, and AutoContracts MSBuild integration are bundled in this single package.


Quick Start

1. Register the services

CaeriusNetBuilder
    .Create(services)
    .WithSqlServer(connectionString)
    .Build();

2. Define a DTO

[GenerateDto]
public sealed partial record UserDto(int Id, string Name, byte Age);

3. Execute a stored procedure

var sp = new StoredProcedureParametersBuilder("dbo", "usp_GetUsers_By_Age", 250)
    .AddParameter("Age", age, SqlDbType.Int)
    .AddInMemoryCache("users:age:" + age, TimeSpan.FromMinutes(5))
    .Build();

var users = await dbContext.QueryAsReadOnlyCollectionAsync<UserDto>(sp, cancellationToken);

Core Concepts

Concept Description
Stored procedures first All queries target SQL Server stored procedures. Inline SQL is not supported.
Compile-time mapping [GenerateDto] and [GenerateTvp] generate ISpMapper<T> and ITvpMapper<T> at build time.
TVP support Pass structured data as Table-Valued Parameters using .AddTvpParameter().
Caching layers Choose Frozen, In-Memory, or Redis caching per query — or combine them.
Multi-result sets Call QueryMultipleIEnumerableAsync<T1, T2, …> to retrieve up to 5 result sets at once.

DTO Mapping

You can map result sets either automatically with source generation or manually by implementing the interface.

Source-generated (recommended)

[GenerateDto]
public sealed partial record UserDto(int Id, string Name, byte Age);

The [GenerateDto] attribute instructs the compiler to generate the ISpMapper<UserDto> implementation automatically.

Manual implementation

public sealed record UserDto(int Id, string Name, byte Age) : ISpMapper<UserDto>
{
    public static UserDto MapFromDataReader(SqlDataReader reader)
        => new(reader.GetInt32(0), reader.GetString(1), reader.GetByte(2));
}

Table-Valued Parameters (TVP)

Use [GenerateTvp] to generate a TVP mapper that matches an existing SQL Server user-defined table type.

1. Define the SQL type

CREATE TYPE dbo.tvp_int AS TABLE (Id INT NOT NULL);

2. Generate the C# mapper

[GenerateTvp(Schema = "dbo", TvpName = "tvp_int")]
public sealed partial record UsersIdsTvp(int Id);

3. Use it in a query

var sp = new StoredProcedureParametersBuilder("dbo", "sp_GetUsers_By_Ids", 1024)
    .AddTvpParameter("Ids", tvpItems)
    .Build();

var users = await dbContext.QueryAsIEnumerableAsync<UserDto>(sp, cancellationToken);

Multi-Result Sets

Retrieve multiple strongly-typed result sets in a single round-trip using QueryMultipleIEnumerableAsync. The multi-result APIs follow the same ValueTask async shape as the rest of the read/write API.

var sp = new StoredProcedureParametersBuilder("dbo", "sp_GetDashboard", 512).Build();

var (users, orders) = await dbContext.QueryMultipleIEnumerableAsync<UserDto, OrderDto>(
    sp, cancellationToken);

You can query up to five result sets: QueryMultipleIEnumerableAsync<T1, T2, T3, T4, T5>.


Caching

Add a cache policy directly on the StoredProcedureParametersBuilder. All three strategies are opt-in per query.

Frozen cache — in-process, immutable

var sp = new StoredProcedureParametersBuilder("dbo", "usp_GetConfig", 64)
    .AddFrozenCache("config:all")
    .Build();

In-Memory cache — in-process, TTL

var sp = new StoredProcedureParametersBuilder("dbo", "usp_GetUsers_By_Age", 250)
    .AddParameter("Age", age, SqlDbType.Int)
    .AddInMemoryCache("users:age:" + age, TimeSpan.FromMinutes(5))
    .Build();

Redis cache — distributed, optional

var sp = new StoredProcedureParametersBuilder("dbo", "usp_GetProducts", 512)
    .AddRedisCache("products:all", TimeSpan.FromMinutes(10))
    .Build();

To enable Redis, register it during setup:

CaeriusNetBuilder
    .Create(services)
    .WithSqlServer(connectionString)
    .WithRedis("localhost:6379")
    .Build();

Transactions

Execute multiple stored procedures atomically within a single transaction scope.

await using var tx = await dbContext.BeginTransactionAsync(IsolationLevel.ReadCommitted, ct);

var sp1 = new StoredProcedureParametersBuilder("dbo", "sp_DebitAccount")
    .AddParameter("AccountId", fromId, SqlDbType.Int)
    .AddParameter("Amount", amount, SqlDbType.Decimal)
    .Build();

var sp2 = new StoredProcedureParametersBuilder("dbo", "sp_CreditAccount")
    .AddParameter("AccountId", toId, SqlDbType.Int)
    .AddParameter("Amount", amount, SqlDbType.Decimal)
    .Build();

await tx.ExecuteNonQueryAsync(sp1, ct);
await tx.ExecuteNonQueryAsync(sp2, ct);
await tx.CommitAsync(ct);

Key design points:

  • State machine — Active → Committed / RolledBack / Poisoned.
  • Single in-flight command — concurrent commands on the same transaction throw InvalidOperationException.
  • Cache bypass — no reads from cache, no writes to cache inside a transaction.
  • Auto-rollback on dispose — if CommitAsync is never called, the transaction rolls back.

Write Operations

Use the execute methods for INSERT, UPDATE, DELETE, and scalar return values.

Execute non-query

var sp = new StoredProcedureParametersBuilder("dbo", "sp_UpdateUser")
    .AddParameter("Guid", guid, SqlDbType.UniqueIdentifier)
    .AddParameter("Age", age, SqlDbType.TinyInt)
    .Build();

int rows = await dbContext.ExecuteNonQueryAsync(sp, cancellationToken);

Execute scalar

var sp = new StoredProcedureParametersBuilder("dbo", "sp_CreateUser")
    .AddParameter("Name", name, SqlDbType.NVarChar)
    .Build();

int newId = await dbContext.ExecuteScalarAsync<int>(sp, cancellationToken);

Available methods

Category Method
Read FirstQueryAsync, QueryAsReadOnlyCollectionAsync, QueryAsIEnumerableAsync, QueryAsImmutableArrayAsync
Write ExecuteNonQueryAsync, ExecuteAsync, ExecuteScalarAsync<T>
Multi-result QueryMultipleIEnumerableAsync<T1,T2><T1,T2,T3,T4,T5>

Aspire Integration

Use WithAspireSqlServer and WithAspireRedis when running under .NET Aspire.

CaeriusNetBuilder.Create(builder)
    .WithAspireSqlServer("CaeriusNet")
    .WithAspireRedis()
    .Build();

Prerequisites

Requirement Minimum version
.NET 10
C# 14
SQL Server 2019

Package Validation

Before publishing, validate the NuGet package contents and smoke-test a consumer project:

pwsh ./.github/scripts/ValidatePackage.ps1 -Configuration Release -OutputDirectory .work/package-validation

Trim/AOT analyzer validation is covered by the Release build. To run it directly:

dotnet build Src/CaeriusNet.csproj --configuration Release -p:IsAotCompatible=true -p:EnableTrimAnalyzer=true

Documentation & Resources


Contributing

Contributions are welcome. Read these first:

  • CONTRIBUTING.md — coding standards, branch model, conventional commits, build/test commands.
  • CODE_OF_CONDUCT.md — Contributor Covenant 2.1.
  • SECURITY.md — how to responsibly report vulnerabilities (private GitHub advisory).
  • SUPPORT.md — where to ask questions and get help.

Quick path:

  1. Open an issue to report a bug or propose a feature.
  2. Fork the repository and create a branch from main.
  3. Submit a pull request with a clear description of your change.

License

CaeriusNet is licensed under the MIT License.

About

CaeriusNet is a high-performance Micro-ORM developed in C# .NET 10+ and optimized for SQL Server 2019 +. It emphasizes code quality, maintainability, and scalability by providing advanced tools for executing stored procedures and managing caching mechanisms.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages