Skip to content

Install and configure CaeriusNet

This quickstart creates a .NET 10 / C# 14 client for a SQL Server 2022 or 2025 stored procedure. CaeriusNet calls only stored procedures; inline SQL is not a runtime feature.

Install

bash
dotnet add package CaeriusNet --version 11.2.0

CaeriusNet.Redis, CaeriusNet.Aspire and CaeriusNet.Contracts are optional packages. Install them only for their corresponding integration.

Build v12 with SDK 10.0.400 (patch roll-forward) and Roslyn 5.9 or later.

Register the database

csharp
using CaeriusNet;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCaeriusNet(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Orders")!));

For production, the configured connection string must use Encrypt=Strict;TrustServerCertificate=False and a server certificate trusted by the application host.

For more than one database, give each additional registration a key and request it with the standard keyed-service mechanism:

csharp
builder.Services.AddCaeriusNet("reporting", options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Reporting")!));

public sealed class Reports(
    [FromKeyedServices("reporting")] ICaeriusNetDbContext reporting)
{
}

Create the stored procedure

sql
CREATE PROCEDURE dbo.usp_User_ByMinimumAge
    @Age int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT Id, Name, Age
    FROM dbo.Users
    WHERE Age >= @Age
    ORDER BY Id;
END

SET NOCOUNT ON is recommended to reduce protocol noise. CaeriusNet also skips rowless frames, so it is not a hidden precondition for a multiple-result-set contract.

Map a row and call the procedure

Use the generator with [GenerateDto], or implement the static mapper contract explicitly:

csharp
using CaeriusNet;
using CaeriusNet.Abstractions;
using CaeriusNet.Commands;
using CaeriusNet.Mappers;
using Microsoft.Data.SqlClient;
using System.Data;
using System.Collections.ObjectModel;

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

public sealed class UserRepository(ICaeriusNetDbContext database)
{
    public ValueTask<ReadOnlyCollection<User>> GetAsync(byte age, CancellationToken ct)
    {
        var command = new StoredProcedureCommandBuilder("dbo", "usp_User_ByMinimumAge")
            .AddParameter("Age", age, SqlDbType.TinyInt)
            .Build();

        return database.QueryReadOnlyCollectionAsync<User>(command, cancellationToken: ct);
    }
}

Parameter names may be passed with or without one @; use the same declared SqlDbType and supply size, precision or scale where the SQL contract needs it. Command validation happens before the connection opens.

Add a local cache

csharp
var command = new StoredProcedureCommandBuilder("dbo", "usp_User_ByMinimumAge")
    .AddParameter("Age", age, SqlDbType.TinyInt)
    .UseInMemoryCache(TimeSpan.FromMinutes(2), slidingExpiration: true)
    .Build();

Cache identity comes from the stored procedure contract, result shape and canonical input values. Do not invent a cache-key string at each call site.

Next steps

Released under the MIT License.