[アップデート] Amazon Aurora DSQL に .NET(Npgsql)と Rust(SQLx)向けコネクターが追加されたので .NET で使ってみた

[アップデート] Amazon Aurora DSQL に .NET(Npgsql)と Rust(SQLx)向けコネクターが追加されたので .NET で使ってみた

2026.04.06

いわさです。

Aurora DSQL の各言語向けコネクターが続々とリリースされています。
コネクターは既存のデータベースドライバーをラップして IAM トークンの自動生成や SSL 設定、コネクションプーリング、OCC リトライなどを透過的に提供してくれるもので、先日は Ruby 向けのコネクターを紹介しました。

https://dev.classmethod.jp/articles/aurora-dsql-connector-for-ruby/

今回、新たに .NET(Npgsql)と Rust(SQLx)向けのコネクターがリリースされました。

https://aws.amazon.com/about-aws/whats-new/2026/03/aurora-dsql-rust-npgsql-connectors/

これで Python、Go、Node.js、Java、Ruby に加えて .NET と Rust もカバーされ、主要な言語のコネクターがほぼ出揃った形ですね。
.NET の場合、従来は AWSSDK.DSQLDSQLAuthTokenGenerator でトークンを生成し、Npgsql の接続文字列にパスワードとして渡す必要がありました。コネクターを使うとこのあたりが全部自動化されます。
今回こちらを確認してみたので紹介します。

使ってみた

では早速 .NET のコネクターを使ってみましょう。
以下のあたりのドキュメントを参考にしました。

https://docs.aws.amazon.com/aurora-dsql/latest/userguide/SECTION_program-with-dsql-connector-for-dotnet-npgsql.html
https://github.com/awslabs/aurora-dsql-connectors/tree/main/dotnet/npgsql

まず、従来の方法とコネクターを使った方法を比較してみます。
従来は AWSSDK.DSQLNpgsql を使って以下のように書く必要がありました。

ManualTokenTest.cs
using Amazon.DSQL;
using Amazon.DSQL.Model;
using Amazon.Runtime;
using Npgsql;

var clusterEndpoint = "ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws";
var region = Amazon.RegionEndpoint.APNortheast1;

// トークンを生成
var credentials = FallbackCredentialsFactory.GetCredentials();
var token = DSQLAuthTokenGenerator.GenerateDbConnectAdminAuthToken(
    credentials, region, clusterEndpoint);

// Npgsql で接続
var connStr = new NpgsqlConnectionStringBuilder
{
    Host = clusterEndpoint,
    Port = 5432,
    Database = "postgres",
    Username = "admin",
    Password = token,
    SslMode = SslMode.VerifyFull
}.ToString();

await using var conn = new NpgsqlConnection(connStr);
await conn.OpenAsync();

await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT 'Hello from Aurora DSQL!' AS greeting";
var greeting = await cmd.ExecuteScalarAsync();
Console.WriteLine(greeting);

トークン生成、SSL モード、リージョン指定、ポート番号など、接続に必要なパラメータを全て自分で管理する必要があります。
さらに、トークンの有効期限は 15 分なので、長時間動作するアプリケーションではトークンのリフレッシュも自前で実装する必要がありました。

これを今回のコネクターで行うと次のようになります。

ConnectTest.cs
using Amazon.AuroraDsql.Npgsql;

var clusterEndpoint = "ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws";

await using var conn = await AuroraDsql.ConnectAsync(new DsqlConfig
{
    Host = clusterEndpoint,
    Profile = "hoge"
});

await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT 'Hello from Aurora DSQL!' AS greeting";
var greeting = await cmd.ExecuteScalarAsync();
Console.WriteLine(greeting);

DsqlConfig にホスト名を渡すだけです。かなりシンプルになりますね。
IAM トークン生成、SSL 設定、リージョン検出がすべて自動で行われます。ホスト名からリージョンが自動検出されるので、リージョンの指定も不要です。

セットアップ

.NET 8.0 以上が必要です。コンソールアプリのプロジェクトを作成して NuGet パッケージをインストールします。

https://www.nuget.org/packages/Amazon.AuroraDsql.Npgsql

% dotnet new console -n DsqlSample
The template "Console App" was created successfully.

Processing post-creation actions...
Restoring /Users/iwasa.takahito/work/hoge0405dsqldotnet/DsqlSample/DsqlSample.csproj:
Restore succeeded.

% cd DsqlSample
% dotnet add package Amazon.AuroraDsql.Npgsql
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/local/share/dotnet/sdk/10.0.101/trustedroots/codesignctl.pem'.

:

info : Writing assets file to disk. Path: /Users/iwasa.takahito/work/hoge0405dsqldotnet/DsqlSample/obj/project.assets.json
log  : Restored /Users/iwasa.takahito/work/hoge0405dsqldotnet/DsqlSample/DsqlSample.csproj (in 2.93 sec).

事前に東京リージョンでクラスターを作成しておきます。

接続テスト

まずは最もシンプルな接続テストから。

ConnectTest.cs
using Amazon.AuroraDsql.Npgsql;

var clusterEndpoint = "ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws";

await using var conn = await AuroraDsql.ConnectAsync(new DsqlConfig
{
    Host = clusterEndpoint,
    Profile = "hoge"
});

await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT 'Hello from Aurora DSQL!' AS greeting";
var greeting = await cmd.ExecuteScalarAsync();
Console.WriteLine(greeting);
% dotnet run
Hello from Aurora DSQL!

AuroraDsql.ConnectAsync にホスト名を渡すだけで接続できていることがわかります。

コネクションプールと CRUD 操作

次に、コネクションプールを使ったテーブルの作成とデータの読み書きを試してみます。
AuroraDsql.CreateDataSourceAsyncNpgsqlDataSource ベースのコネクションプールを作成できます。

CrudTest.cs
using Amazon.AuroraDsql.Npgsql;

var clusterEndpoint = "ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws";

// コネクションプール作成(OCC リトライ有効)
await using var ds = await AuroraDsql.CreateDataSourceAsync(new DsqlConfig
{
    Host = clusterEndpoint,
    Profile = "hoge",
    OccMaxRetries = 3
});

// テーブル作成
await ds.ExecWithRetryAsync(
    "CREATE TABLE IF NOT EXISTS hogeusers (id UUID DEFAULT gen_random_uuid() PRIMARY KEY, name TEXT NOT NULL)");

// データ挿入(トランザクション + OCC リトライ)
await ds.WithTransactionRetryAsync(async conn =>
{
    await using var cmd1 = conn.CreateCommand();
    cmd1.CommandText = "INSERT INTO hogeusers (name) VALUES (@name)";
    cmd1.Parameters.AddWithValue("name", "hoge");
    await cmd1.ExecuteNonQueryAsync();

    await using var cmd2 = conn.CreateCommand();
    cmd2.CommandText = "INSERT INTO hogeusers (name) VALUES (@name)";
    cmd2.Parameters.AddWithValue("name", "fuga");
    await cmd2.ExecuteNonQueryAsync();
});

// データ取得
await using (var conn = await ds.OpenConnectionAsync())
{
    await using var cmd = conn.CreateCommand();
    cmd.CommandText = "SELECT id, name FROM hogeusers";
    await using var reader = await cmd.ExecuteReaderAsync();
    while (await reader.ReadAsync())
    {
        Console.WriteLine($"{reader["id"]} : {reader["name"]}");
    }
}
% dotnet run
04848cd0-1916-43d2-a50f-72286995c750 : hoge
3cc92d8e-e1b2-4740-8a13-2534e849d232 : hoge
4f87f7ee-c51a-448e-acc5-5cf10f7bf2d7 : fuga
eaa3c339-a726-4346-a31a-254ac28dc80f : fuga

テーブル作成、データ挿入、取得がすべて問題なく動作しました。

DDL の実行には ExecWithRetryAsync を使い、トランザクション付きの書き込みには WithTransactionRetryAsync を使います。
WithTransactionRetryAsync は内部で BEGIN/COMMIT/ROLLBACK を管理してくれるので、コールバック内ではデータベース操作だけを書けば良いです。

OCC リトライ

Aurora DSQL は楽観的同時実行制御(OCC)を採用しています。2 つのトランザクションが同じデータを変更した場合、先にコミットした方が勝ち、後からコミットしようとした方は OCC エラーを受け取ります。

コネクターでは DsqlConfigOccMaxRetries を設定することで、OCC 競合時に指数バックオフ付きで自動リトライしてくれます。

// OCC リトライ付き更新
await ds.WithTransactionRetryAsync(async conn =>
{
    await using var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE hogeusers SET name = @newName WHERE name = @oldName";
    cmd.Parameters.AddWithValue("newName", "piyo");
    cmd.Parameters.AddWithValue("oldName", "hoge");
    await cmd.ExecuteNonQueryAsync();
});

WithTransactionRetryAsync はリトライのたびに新しいコネクションを取得して BEGIN からやり直してくれるので、コールバック内はリトライセーフな操作だけを書く必要があります。

設定オプション

DsqlConfig で設定できるオプションは以下のとおりです。

オプション デフォルト 説明
Host (必須) クラスターエンドポイントまたは 26 文字のクラスター ID
Region (自動検出) AWS リージョン。Host がクラスター ID の場合は必須
User "admin" データベースユーザー
Database "postgres" データベース名
Port 5432 ポート番号
Profile null AWS プロファイル名
CustomCredentialsProvider null カスタム AWS 認証情報プロバイダー
TokenDurationSecs null(SDK デフォルト 900 秒) トークンの有効期間(秒)
OccMaxRetries null(無効) OCC リトライの最大回数
LoggerFactory null ロガーファクトリ(リトライ時の警告ログなど)
ConfigureConnectionString null Npgsql 接続文字列のカスタマイズコールバック

接続文字列形式もサポートされています。

await using var ds = await AuroraDsql.CreateDataSourceAsync(
    "postgres://admin@ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws/postgres?profile=dev");

また、プールのデフォルト設定として MaxPoolSize=10ConnectionLifetime=3300(55 分)、ConnectionIdleLifetime=600(10 分)が適用されます。ConfigureConnectionString コールバックでこれらをカスタマイズすることも可能です。ただし、SSL(SslMode=VerifyFullSslNegotiation=Direct)と Enlist=false はセキュリティ上の理由でオーバーライドできないみたいです。

await using var ds = await AuroraDsql.CreateDataSourceAsync(new DsqlConfig
{
    Host = clusterEndpoint,
    ConfigureConnectionString = csb =>
    {
        csb.MaxPoolSize = 20;
        csb.MinPoolSize = 2;
        csb.CommandTimeout = 60;
    }
});

Rust コネクターについて

今回のアップデートでは Rust(SQLx)向けのコネクターも同時にリリースされています。

https://docs.aws.amazon.com/aurora-dsql/latest/userguide/SECTION_program-with-dsql-connector-for-rust-sqlx.html
https://github.com/awslabs/aurora-dsql-connectors/tree/main/rust/sqlx

Rust のコネクターも設計思想は .NET と同じで、接続文字列を渡すだけで IAM トークン生成や SSL 設定が自動化されます。
poolocc の feature フラグを opt-in で有効にする形式で、SQLx の慣習に沿った設計になっています。

use sqlx::Row;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let pool = aurora_dsql_sqlx_connector::pool::connect(
        "postgres://admin@ivtvahlywbnhlbci5ujpzw5wja.dsql.ap-northeast-1.on.aws/postgres",
    )
    .await?;

    let row = sqlx::query("SELECT 'Hello, DSQL!' as greeting")
        .fetch_one(&pool)
        .await?;
    let greeting: &str = row.get("greeting");
    println!("{}", greeting);

    pool.close().await;
    Ok(())
}

Rust のコネクターではプール利用時にバックグラウンドタスクがトークンの有効期限の 80% 経過時点で自動リフレッシュしてくれるみたいです。

Connection pools: A background task refreshes the token at 80% of the token duration. Call pool.close().await to stop the refresh task and release pool resources.

https://docs.aws.amazon.com/aurora-dsql/latest/userguide/SECTION_program-with-dsql-connector-for-rust-sqlx.html

さいごに

本日は Amazon Aurora DSQL に .NET(Npgsql)と Rust(SQLx)向けコネクターが追加されたので .NET の方を中心に確認してみました。

DsqlConfig にホスト名を渡すだけで接続でき、WithTransactionRetryAsync で OCC リトライも簡単に組み込めるので、Npgsql を普段使っている方にはかなり馴染みやすい API だと思います。
これで主要な言語のコネクターがほぼ出揃ったので、Aurora DSQL を本格的に使う際にはコネクターを活用していきたいですね。

この記事をシェアする

関連記事