Se connecter depuis .NET, Rust et le reste
AvancéQuel que soit le langage, le schéma est le même : une chaîne de connexion, un pool de connexions, des requêtes paramétrées.
Host=db.exemple.fr;Port=5432;Database=app;Username=app_api;Password=...;SSL Mode=VerifyFull;
Maximum Pool Size=20;Timeout=15;Command Timeout=30
.NET : Npgsql (et EF Core)#
// Enregistrer un NpgsqlDataSource : il gère le pool
builder.Services.AddNpgsqlDataSource(connectionString);
app.MapGet("/clients/{id:long}", async (long id, NpgsqlDataSource db, CancellationToken ct) =>
{
await using var cmd = db.CreateCommand("SELECT id, nom FROM clients WHERE id = $1");
cmd.Parameters.AddWithValue(id);
await using var reader = await cmd.ExecuteReaderAsync(ct);
return await reader.ReadAsync(ct) ? Results.Ok(new { Id = reader.GetInt64(0), Nom = reader.GetString(1) })
: Results.NotFound();
});
// Avec EF Core : options.UseNpgsql(connectionString)
Rust : sqlx#
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(20)
.connect(&std::env::var("DATABASE_URL")?)
.await?;
let client = sqlx::query!("SELECT id, nom FROM clients WHERE id = $1", 42_i64)
.fetch_optional(&pool)
.await?;
Ce qui compte, dans tous les cas#
| Sujet | Bonne pratique |
|---|---|
| Pool | Un pool partagé par processus, taille limitée (voir le calcul ci-dessous) |
| Timeouts | Délai de connexion et délai de commande : ne jamais attendre indéfiniment |
| Paramètres | Toujours des paramètres, jamais de concaténation |
| Libération | Rendre la connexion au pool rapidement (await using, fin de portée) |
| Migrations | Un outil dédié, exécuté hors du démarrage de chaque instance |
Dimensionner les pools#
Avec N instances d'application et un pool de P connexions chacune, la base reçoit jusqu'à N × P connexions. Choisissez P pour que N × P reste sous la limite de la base (ou de son pooleur), avec de la marge pour les migrations et les outils.
Piège : augmenter le pool « parce que l'application attend une connexion » aggrave souvent le problème : la base sature. Cherchez d'abord pourquoi les connexions sont retenues longtemps (transaction ouverte pendant un appel HTTP, requête lente).