</>
Plan du cours — 54/64

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#

SujetBonne pratique
PoolUn pool partagé par processus, taille limitée (voir le calcul ci-dessous)
TimeoutsDélai de connexion et délai de commande : ne jamais attendre indéfiniment
ParamètresToujours des paramètres, jamais de concaténation
LibérationRendre la connexion au pool rapidement (await using, fin de portée)
MigrationsUn 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).