Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 70 additions & 152 deletions docs/site/src/content/docs/host/aspire-integration.md

Large diffs are not rendered by default.

251 changes: 36 additions & 215 deletions docs/site/src/content/docs/host/client.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,48 +1,70 @@
---
title: ADO.NET database configuration
description: Learn about ADO.NET database configurations in .NET Orleans.
ms.date: 05/23/2025
ms.topic: how-to
description: Find Orleans ADO.NET schema scripts and provider invariants.
ms.date: 08/02/2026
ms.topic: reference
---

# ADO.NET database configuration

The following sections contain links to SQL scripts for configuring your database and the corresponding ADO.NET invariant used to configure ADO.NET providers in Orleans. Customize these scripts as needed for your deployment. Before executing scripts for Clustering, Persistence, or Reminders, you need to create the main tables using the Main scripts.
Orleans keeps its ADO.NET schema scripts beside each provider's source. Run the main script before the capability scripts. Use scripts from the same Orleans release as the packages deployed by the application.

## Driver invariants

| Database | Driver package | Orleans invariant |
|---|---|---|
| SQL Server | [Microsoft.Data.SqlClient](https://www.nuget.org/packages/Microsoft.Data.SqlClient/) | `Microsoft.Data.SqlClient` |
| PostgreSQL | [Npgsql](https://www.nuget.org/packages/Npgsql/) | `Npgsql` |
| MySQL/MariaDB | [MySql.Data](https://www.nuget.org/packages/MySql.Data/) | `MySql.Data.MySqlClient` |
| Oracle | [Oracle.ManagedDataAccess.Core](https://www.nuget.org/packages/Oracle.ManagedDataAccess.Core/) | `Oracle.DataAccess.Client` |

> [!IMPORTANT]
> Use `Microsoft.Data.SqlClient`, not `System.Data.SqlClient`, for SQL Server.

## Main scripts

| Database | Script | NuGet package| ADO.NET invariant |
|--|--|--|--|
| SQL Server | [SQLServer-Main.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/SQLServer-Main.sql) | [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient/) | `System.Data.SqlClient` |
| MySQL / MariaDB | [MySQL-Main.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/MySQL-Main.sql) | [MySql.Data](https://www.nuget.org/packages/MySql.Data/) | `MySql.Data.MySqlClient` |
| PostgreSQL | [PostgreSQL-Main.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/PostgreSQL-Main.sql) | [Npgsql](https://www.nuget.org/packages/Npgsql/) | `Npgsql` |
| Oracle | [Oracle-Main.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/Oracle-Main.sql) | [ODP.net](https://www.nuget.org/packages/Oracle.ManagedDataAccess/) | `Oracle.DataAccess.Client` |
- [SQL Server](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/SQLServer-Main.sql)
- [PostgreSQL](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/PostgreSQL-Main.sql)
- [MySQL/MariaDB](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/MySQL-Main.sql)
- [Oracle](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/Oracle-Main.sql)
- [SQLite](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Shared/Sqlite-Main.sql) for supported local persistence scenarios

## Clustering

| Database | Script | NuGet package| ADO.NET invariant |
|--|--|--|--|
| SQL Server | [SQLServer-Clustering.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/SQLServer-Clustering.sql) | [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient/) | `System.Data.SqlClient` |
| MySQL / MariaDB | [MySQL-Clustering.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/MySQL-Clustering.sql) | [MySql.Data](https://www.nuget.org/packages/MySql.Data/) | `MySql.Data.MySqlClient` |
| PostgreSQL | [PostgreSQL-Clustering.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/PostgreSQL-Clustering.sql) | [Npgsql](https://www.nuget.org/packages/Npgsql/) | `Npgsql` |
| Oracle | [Oracle-Clustering.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/Oracle-Clustering.sql) | [ODP.net](https://www.nuget.org/packages/Oracle.ManagedDataAccess/) | `Oracle.DataAccess.Client` |
- [SQL Server](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/SQLServer-Clustering.sql)
- [PostgreSQL](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/PostgreSQL-Clustering.sql)
- [MySQL/MariaDB](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/MySQL-Clustering.sql)
- [Oracle](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Clustering.AdoNet/Oracle-Clustering.sql)

## Persistence

| Database | Script | NuGet package| ADO.NET invariant |
|--|--|--|--|
| SQL Server* | [SQLServer-Persistence.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/SQLServer-Persistence.sql) | [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient/) | `System.Data.SqlClient` |
| MySQL / MariaDB | [MySQL-Persistence.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/MySQL-Persistence.sql) | [MySql.Data](https://www.nuget.org/packages/MySql.Data/) | `MySql.Data.MySqlClient` |
| PostgreSQL | [PostgreSQL-Persistence.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/PostgreSQL-Persistence.sql) | [Npgsql](https://www.nuget.org/packages/Npgsql/) | `Npgsql` |
| Oracle | [Oracle-Persistence.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/Oracle-Persistence.sql) | [ODP.net](https://www.nuget.org/packages/Oracle.ManagedDataAccess/) | `Oracle.DataAccess.Client` |

\* If you're using Orleans v3.x use this script template: <https://github.com/dotnet/orleans/blob/3.x/src/AdoNet/Orleans.Persistence.AdoNet/SQLServer-Persistence.sql>
- [SQL Server](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/SQLServer-Persistence.sql)
- [PostgreSQL](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/PostgreSQL-Persistence.sql)
- [MySQL/MariaDB](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/MySQL-Persistence.sql)
- [Oracle](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/Oracle-Persistence.sql)
- [SQLite](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Persistence.AdoNet/Sqlite-Persistence.sql)

## Reminders

| Database | Script | NuGet package| ADO.NET invariant |
|--|--|--|--|
| SQL Server | [SQLServer-Reminders.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/SQLServer-Reminders.sql) | [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient/) | `System.Data.SqlClient` |
| MySQL / MariaDB | [MySQL-Reminders.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/MySQL-Reminders.sql) | [MySql.Data](https://www.nuget.org/packages/MySql.Data/) | `MySql.Data.MySqlClient` |
| PostgreSQL | [PostgreSQL-Reminders.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/PostgreSQL-Reminders.sql) | [Npgsql](https://www.nuget.org/packages/Npgsql/) | `Npgsql` |
| Oracle | [Oracle-Reminders.sql](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/Oracle-Reminders.sql) | [ODP.net](https://www.nuget.org/packages/Oracle.ManagedDataAccess/) | `Oracle.DataAccess.Client` |
- [SQL Server](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/SQLServer-Reminders.sql)
- [PostgreSQL](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/PostgreSQL-Reminders.sql)
- [MySQL/MariaDB](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/MySQL-Reminders.sql)
- [Oracle](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.Reminders.AdoNet/Oracle-Reminders.sql)

## Grain directory scripts

- [SQL Server](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.GrainDirectory.AdoNet/SQLServer-GrainDirectory.sql)
- [PostgreSQL](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.GrainDirectory.AdoNet/PostgreSQL-GrainDirectory.sql)
- [MySQL/MariaDB](https://github.com/dotnet/orleans/blob/main/src/AdoNet/Orleans.GrainDirectory.AdoNet/MySQL-GrainDirectory.sql)

Not every capability supports every database. The presence of a script in the provider directory is the authoritative support signal for that Orleans release.

## Apply and upgrade schemas

1. Back up application data according to the database recovery policy.
2. Apply the main script for a new database.
3. Apply the script for each configured Orleans capability.
4. Review and apply scripts under the provider's `Migrations` directory when upgrading from an older schema.
5. Validate with a staging cluster using the same driver and database engine version.

See [Configure ADO.NET providers](configuring-ado-dot-net-providers.md) for host configuration.
Original file line number Diff line number Diff line change
@@ -1,170 +1,46 @@
---
title: Client configuration
description: Learn about client configurations in .NET Orleans.
ms.date: 01/21/2026
description: Configure an Orleans external client.
ms.date: 08/02/2026
ms.topic: how-to
zone_pivot_groups: orleans-version
ms.custom: sfi-ropc-nochange
---

# Client configuration

:::zone target="docs" pivot="orleans-7-0,orleans-8-0,orleans-9-0,orleans-10-0"
An external client runs outside a silo process and reaches the cluster through silo gateways. Install [Microsoft.Orleans.Client](https://www.nuget.org/packages/Microsoft.Orleans.Client), call <xref:Microsoft.Extensions.Hosting.OrleansClientGenericHostExtensions.UseOrleansClient*>, and configure the same cluster identity and clustering provider as the silos:

Configure a client for connecting to a cluster of silos and sending requests to grains programmatically via an <xref:Microsoft.Extensions.Hosting.IHostBuilder> and several supplemental option classes. Like silo options, client option classes follow the [Options pattern in .NET](../../../core/extensions/options.md).
:::code language="csharp" source="../snippets/hosting/HostingExamples.cs" id="external_client":::

:::zone-end

:::zone target="docs" pivot="orleans-3-x"

Configure a client for connecting to a cluster of silos and sending requests to grains programmatically via an <xref:Orleans.ClientBuilder> and several supplemental option classes. Like silo options, client option classes follow the [Options pattern in .NET](../../../core/extensions/options.md).

:::zone-end

> [!TIP]
> If you just want to start a local silo and a local client for development purposes, see [Local development configuration](local-development-configuration.md).

:::zone target="docs" pivot="orleans-8-0,orleans-9-0,orleans-10-0"

> [!TIP]
> If you're using [Aspire](../aspire-integration.md), client configuration is handled automatically. Aspire injects <xref:Orleans.Configuration.ClusterOptions.ClusterId>, <xref:Orleans.Configuration.ClusterOptions.ServiceId>, and clustering provider settings via environment variables, so you can use the simpler parameterless <xref:Microsoft.Extensions.Hosting.OrleansClientGenericHostExtensions.UseOrleansClient*> method. See [Orleans and Aspire integration](../aspire-integration.md) for the recommended approach.

:::zone-end

Add the [Microsoft.Orleans.Clustering.AzureStorage](https://www.nuget.org/packages/Microsoft.Orleans.Clustering.AzureStorage) NuGet package to your client project.

There are several key aspects of client configuration:

- Orleans clustering information
- Clustering provider
- Application parts

Example of a client configuration:

:::zone target="docs" pivot="orleans-7-0,orleans-8-0,orleans-9-0,orleans-10-0"

### [Microsoft Entra ID (recommended)](#tab/entra-id)

Using a `TokenCredential` with a service URI is the recommended approach. This pattern avoids storing secrets in configuration and leverages Microsoft Entra ID for secure authentication.

<xref:Azure.Identity.DefaultAzureCredential> provides a credential chain that works seamlessly across local development and production environments. During development, it uses your Azure CLI or Visual Studio credentials. In production on Azure, it automatically uses the managed identity assigned to your resource.

[!INCLUDE [credential-chain-guidance](../../includes/credential-chain-guidance.md)]

```csharp
using Azure.Identity;

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
clientBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "MyOrleansService";
})
.UseAzureStorageClustering(options =>
{
options.ConfigureTableServiceClient(
new Uri("https://<your-storage-account>.table.core.windows.net"),
new DefaultAzureCredential());
});
});

using var host = builder.Build();
await host.StartAsync();
```

### [Connection string](#tab/connection-string)

```csharp
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
clientBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "MyOrleansService";
})
.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(
builder.Configuration["ORLEANS_AZURE_STORAGE_CONNECTION_STRING"]));
});

using var host = builder.Build();
await host.StartAsync();
```

---

:::zone-end

:::zone target="docs" pivot="orleans-3-x"

:::code language="csharp" source="snippets-v3/client-config/Configuration.cs" id="full_client_config":::

:::zone-end

Let's break down the steps used in this sample:
Client settings participate in the [.NET options pattern](https://learn.microsoft.com/dotnet/core/extensions/options). The host starts Orleans before later registered hosted services and stops it with the rest of the application. Resolve <xref:Orleans.IClusterClient> or <xref:Orleans.IGrainFactory> from [.NET dependency injection](https://learn.microsoft.com/dotnet/core/extensions/dependency-injection); don't build a second client singleton manually.

## Orleans clustering information

```csharp
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "orleans-docker";
options.ServiceId = "AspNetSampleApp";
})
```
- <xref:Orleans.Configuration.ClusterOptions.ServiceId> identifies the logical Orleans application and should remain stable.
- <xref:Orleans.Configuration.ClusterOptions.ClusterId> identifies one deployment of that service. Use a different value to isolate environments or parallel deployments.
- The client clustering provider discovers gateway-enabled silos. Its settings must point to the same membership data as the silos.

Here, we set two things:
### Clustering provider

- The <xref:Orleans.Configuration.ClusterOptions.ClusterId?displayProperty=nameWithType> to `"my-first-cluster"`: This is a unique ID for the Orleans cluster. All clients and silos using this ID can directly talk to each other. Some might choose to use a different <xref:Orleans.Configuration.ClusterOptions.ClusterId> for each deployment, for example.
- The <xref:Orleans.Configuration.ClusterOptions.ServiceId?displayProperty=nameWithType> to `"AspNetSampleApp"`: This is a unique ID for your application, used by some providers (e.g., persistence providers). This ID should remain stable across deployments.

## Clustering provider

:::zone target="docs" pivot="orleans-7-0,orleans-8-0,orleans-9-0,orleans-10-0"

### [Microsoft Entra ID (recommended)](#tab/entra-id)

[!INCLUDE [credential-chain-guidance](../../includes/credential-chain-guidance.md)]

```csharp
clientBuilder.UseAzureStorageClustering(options =>
{
options.ConfigureTableServiceClient(
new Uri("https://<your-storage-account>.table.core.windows.net"),
new DefaultAzureCredential());
});
```

### [Connection string](#tab/connection-string)

```csharp
.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString));
```

---
Common production [clustering packages](server-configuration.md#clustering-provider) include Azure Table Storage, ADO.NET, Redis, Azure Cosmos DB, DynamoDB, Consul, and ZooKeeper. Static and localhost clustering are intended for development. Kubernetes hosting is a silo integration, not a client clustering provider.

:::zone-end
When Aspire supplies the Orleans resource, register the corresponding keyed service client and use the parameterless form:

:::zone target="docs" pivot="orleans-3-x"
:::code language="csharp" source="../snippets/aspire/Client/ClientProgram.cs" id="client_basic_config":::

:::code language="csharp" source="snippets-v3/client-config/Configuration.cs" id="azure_clustering":::
## Connection resiliency

:::zone-end
Orleans registers a default <xref:Orleans.IClientConnectionRetryFilter>. It retries eligible initial connection failures with linear backoff, up to 15 retries. Host startup fails if the client still can't connect, the host is stopping, or the failure isn't considered retryable.

The client discovers all available gateways in the cluster using this provider. Several providers are available; here, we use the Azure Table provider.
Override the policy only when the application has different startup requirements:

For more information, see [Server configuration](server-configuration.md).
:::code language="csharp" source="../snippets/hosting/HostingExamples.cs" id="client_retry":::

:::zone target="docs" pivot="orleans-3-x"
Bound every custom retry policy and honor the cancellation token so deployments can fail fast and shutdown isn't delayed indefinitely.

## Application parts
Initial connection retries don't make grain calls idempotent. A call can fail after the target started processing it, so retry application operations only when their semantics tolerate duplicates. Grain references remain usable after transient connectivity failures.

:::code language="csharp" source="snippets-v3/client-config/Configuration.cs" id="application_parts":::
## Gateway behavior

For more information, see [Server configuration](server-configuration.md).
Configure gateway refresh and connection behavior through <xref:Orleans.Configuration.GatewayOptions> or `Orleans:Gateway`. Orleans refreshes the gateway list from the clustering provider and reconnects as gateways become unavailable. Expose gateway endpoints only to client networks that require them; silo-to-silo traffic uses a separate endpoint.

:::zone-end
For a co-hosted client, use <xref:Microsoft.Extensions.Hosting.OrleansSiloGenericHostExtensions.UseOrleans*> instead. The silo's client communicates directly with the cluster and doesn't require a gateway hop.
Loading
Loading