Skip to content

Server (Silo)

The server package registers ADO.NET provider builders for Orleans clustering, grain storage, and reminders — all resolved automatically from the configuration that Aspire injects via [assembly: RegisterProvider] attributes.

Call silo.UseAdoNet() inside the UseOrleans lambda. Because it’s on ISiloBuilder, you can compose it with other silo features:

using Shiny.Aspire.Orleans.Server;
var builder = WebApplication.CreateBuilder(args);
builder.UseOrleans(silo =>
{
silo.UseAdoNet();
// add other silo configuration here (e.g. silo.AddDashboard())
});
var app = builder.Build();
app.Run();
public static ISiloBuilder UseAdoNet(this ISiloBuilder siloBuilder)

Marker extension for discoverability. The actual provider registration happens automatically via [assembly: RegisterProvider] attributes when the package is referenced. Providers are registered for all three database types (PostgreSQL, SQL Server, MySQL) across Clustering, GrainStorage, and Reminders.

When Orleans calls ApplyConfiguration during UseOrleans(), it reads the Aspire-injected configuration (e.g. Orleans:Clustering:ProviderType = "PostgresDatabase") and resolves the matching provider builder automatically. The provider builder maps the database type to the correct ADO.NET invariant and resolves the connection string from the ServiceKey.

This means:

  • No manual configuration — providers are resolved automatically from Aspire config
  • No connection string plumbing — connection strings are resolved via the injected ServiceKey
  • No invariant mapping — the correct ADO.NET invariant is auto-detected from the provider type

Aspire automatically injects the following configuration when you use .WithReference(orleans) in the AppHost:

Orleans:Clustering:ProviderType = "PostgresDatabase"
Orleans:Clustering:ServiceKey = "orleans-db"
Orleans:GrainStorage:Default:ProviderType = "PostgresDatabase"
Orleans:GrainStorage:Default:ServiceKey = "orleans-db"
Orleans:Reminders:ProviderType = "PostgresDatabase"
Orleans:Reminders:ServiceKey = "orleans-db"
ConnectionStrings:orleans-db = "Host=...;Database=..."

The registered provider builders read these sections and configure Orleans with the matching ADO.NET providers (Npgsql, Microsoft.Data.SqlClient, or MySql.Data.MySqlClient).

The server package supports multiple named grain storage providers:

// AppHost
var orleans = builder.AddOrleans("cluster")
.WithClustering(db)
.WithGrainStorage("Default", db)
.WithGrainStorage("Archive", archiveDb)
.WithDatabaseSetup(db);
// Grain
public class MyGrain(
[PersistentState("state", "Default")] IPersistentState<MyState> state,
[PersistentState("archive", "Archive")] IPersistentState<ArchiveState> archive
) : Grain, IMyGrain { }

Each named storage provider reads its configuration from Orleans:GrainStorage:{Name}:ProviderType and Orleans:GrainStorage:{Name}:ServiceKey.