Skip to main content
Entity Framework Core (EF Core) est l’ORM de .NET, et Npgsql est son fournisseur PostgreSQL. Dans ce guide, vous allez développer une API minimale ASP.NET Core, créer sa table au moyen d’une migration EF Core et exposer des endpoints de création, de lecture, de mise à jour et de suppression. Toutes les connexions utilisent TLS avec une vérification complète des certificats.

Prérequis

  • Le SDK .NET 10. Ce guide a été testé avec le SDK .NET 10.0.401, EF Core 10.0.12 et Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 (Npgsql 10.0.3).
  • Un compte ClickHouse Cloud
  • psql, pour créer la base de données. Vous pouvez également exécuter le statement CREATE DATABASE dans la console SQL.

Créer un service ClickHouse Managed Postgres

Dans la console ClickHouse Cloud, cliquez sur New service et sélectionnez Postgres. L’instance est prête en quelques minutes. Pour une présentation pas à pas, consultez le guide de démarrage rapide.

Obtenir vos informations de connexion

Cliquez sur Connect dans la barre latérale gauche de votre service. Laissez Directly sélectionné, activez Use SSL, puis copiez le mot de passe et le nom d’hôte du serveur. Cliquez ensuite sur Download CA certificate. Vous pouvez également télécharger le certificat plus tard depuis Settings → CA Certificate. Ce certificat est propre à votre instance : il permet à Npgsql de vérifier qu’il communique bien avec votre serveur. Dans ce guide, l’application comme les migrations EF Core se connectent directement à Postgres sur le port 5432. Une application ASP.NET Core est un processus de longue durée, et Npgsql y gère déjà un pool de connexions (jusqu’à 100 par chaîne de connexion par défaut) ; un second pooler est donc inutile. Si vous exécutez de nombreuses instances de l’application, consultez Utiliser PgBouncer. La fenêtre modale Connect ne propose pas d’onglet .NET, et Npgsql n’accepte pas l’URL postgresql:// de l’onglet url : il utilise des chaînes de connexion au format Keyword=Value. Reprenez les valeurs de l’URL et faites-les correspondre aux mots-clés Npgsql :

Configurer le projet

Créez un projet ASP.NET Core, ajoutez le fournisseur Npgsql pour EF Core ainsi que le paquet EF Core Design (outils de conception), puis installez l’outil en ligne de commande dotnet ef :
Vous partez d’une application existante ?Ignorez dotnet new web. Si votre application utilise EF Core avec SQLite ou un autre fournisseur :
  • Exécutez dotnet remove package Microsoft.EntityFrameworkCore.Sqlite et dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL. Installez également Microsoft.EntityFrameworkCore.Design et l’outil dotnet-ef si vous ne les avez pas déjà.
  • Dans Program.cs, remplacez UseSqlite par UseNpgsql, puis supprimez la chaîne de connexion SQLite de appsettings.json.
  • Les migrations étant propres à chaque fournisseur, supprimez le dossier Migrations. Vous créerez une nouvelle migration initiale à l’étape Créer le schéma.
Poursuivez ensuite avec Configurer la connexion en remplaçant TodoDb par le nom de la chaîne de connexion de votre application, puis ignorez Définir le modèle.
Sous macOS, activez TLS 1.3ClickHouse Managed Postgres n’accepte que TLS 1.3. Par défaut, .NET sous macOS ne prend pas en charge TLS 1.3 : toutes les connexions échouent alors avec Exception while performing SSL handshake et l’erreur interne bad protocol version. .NET 10 peut s’appuyer à la place sur Network.framework d’Apple, qui prend en charge TLS 1.3. Ajoutez ceci à l’élément <Project> de TodoApi.csproj :
Ce paramètre s’applique à l’application comme à dotnet ef, et n’a aucun effet sous Linux ou Windows. Vous pouvez aussi définir plutôt la variable d’environnement DOTNET_SYSTEM_NET_SECURITY_USENETWORKFRAMEWORK=1.

Configurer la connexion

Déplacez le certificat de CA téléchargé dans le répertoire du projet et renommez-le en ca-certificate.pem. Créez une base de données pour l’application. Remplacez <PASSWORD> et l’hôte par les valeurs affichées dans la fenêtre modale Connect :
Stockez la chaîne de connexion à l’aide du Secret Manager afin que le mot de passe n’apparaisse ni dans appsettings.json ni dans le gestionnaire de versions :
ASP.NET Core lit les secrets utilisateur dans l’environnement Development, que dotnet run et dotnet ef utilisent par défaut. En production, définissez plutôt la variable d’environnement ConnectionStrings__TodoDb. Avec SSL Mode=VerifyFull, Npgsql vérifie que le certificat du serveur est signé par la CA indiquée dans Root Certificate et qu’il correspond au nom d’hôte. Npgsql résout un path Root Certificate relatif par rapport au répertoire de travail courant, c’est-à-dire le répertoire du projet lorsque vous utilisez dotnet run et dotnet ef. Utilisez un path absolu si vous lancez l’application depuis un autre emplacement.
Si la CA est incorrecte ou absente, ou si l’hôte ne correspond pas au certificat (par exemple, lorsque vous vous connectez via une adresse IP), la connexion échoue avec Exception while performing SSL handshake et l’erreur interne The remote certificate was rejected by the provided RemoteCertificateValidationCallback. Si le fichier Root Certificate n’existe pas, l’erreur interne est Could not find file. Notez également que :
  • Par défaut, Npgsql utilise SSL Mode=Prefer, et SSL Mode=Require ne vérifie pas non plus le certificat, même si vous définissez Root Certificate. Définissez toujours SSL Mode=VerifyFull.
  • Npgsql lit les variables d’environnement PGSSLROOTCERT et PGPASSWORD, mais pas PGHOST ni PGSSLMODE. Les variables de l’onglet env de la fenêtre modale Connect ne suffisent donc pas à elles seules.

Définir le modèle

Créez le fichier Todo.cs contenant la classe d’entité :
Todo.cs
Créez le fichier TodoDb.cs contenant le DbContext :
TodoDb.cs
Remplacez le contenu de Program.cs. Ce code enregistre TodoDb auprès du fournisseur Npgsql et associe un endpoint à chaque opération. Dans une application existante, seul l’appel à AddDbContext avec UseNpgsql est nécessaire :
Program.cs
L’endpoint /db/tls lit pg_stat_ssl pour la session de base de données de l’application elle-même, ce qui vous permet de vérifier que la connexion est bien chiffrée.

Créer le schéma

Générez une migration à partir du modèle, puis appliquez-la :
dotnet ef migrations add écrit la migration dans le dossier Migrations, et dotnet ef database update l’applique puis l’enregistre dans la table __EFMigrationsHistory. Lors de la première exécution, EF Core journalise l’échec d’un SELECT sur __EFMigrationsHistory avant de créer la table ; vous pouvez ignorer ce message. Avant d’appliquer les migrations, EF Core acquiert un verrou afin que deux déploiements ne puissent pas migrer la même base de données simultanément. Avec Npgsql, ce verrou est un LOCK TABLE sur __EFMigrationsHistory au sein de la transaction de migration, et non un verrou consultatif (advisory lock) au niveau de la session ; il est donc libéré à la fin de la transaction.

Exécuter et vérifier

Démarrez l’application sur le port 3115 :
Dans un second terminal, créez deux tâches, marquez la première comme terminée, puis supprimez la seconde :
La requête DELETE renvoie 204 No Content : sa ligne est donc vide. Vérifiez que la session de base de données de l’application utilise TLS :
Ouvrez http://localhost:3115/todos dans votre navigateur pour afficher la liste des tâches restantes :
Pour afficher les données dans la console, ouvrez la console SQL depuis la barre latérale gauche de votre service, développez guide_dotnet puis public, et cliquez sur la table Todos. EF Core utilise les noms de classes et de propriétés comme identifiants entre guillemets : la table s’appelle donc "Todos" et les colonnes "Id", "Title", etc. La table contient la ligne restante :

Utiliser PgBouncer

Npgsql ouvre jusqu’à 100 connexions par instance d’application (Maximum Pool Size). Si, cumulées, de nombreuses instances approchent la limite de connexions de Postgres, connectez plutôt l’application via le PgBouncer intégré. Sélectionnez via PgBouncer dans la fenêtre modale Connect, puis remplacez le port de la chaîne de connexion par 6432 :
Le même certificat de CA fonctionne. PgBouncer s’exécute en mode de pool de connexions par transaction : chaque transaction peut donc s’exécuter sur une connexion Postgres différente. Avec les paramètres par défaut d’EF Core et de Npgsql, vous n’avez rien d’autre à modifier :
  • Requêtes préparées : EF Core ne prépare pas les statements, et la préparation automatique de Npgsql est désactivée par défaut (Max Auto Prepare=0) ; les requêtes utilisent donc des statements non nommés, qui fonctionnent via PgBouncer. Conservez cette configuration. Via PgBouncer, les requêtes préparées issues de Max Auto Prepare ou de NpgsqlCommand.Prepare échouent de manière intermittente avec 08P01: prepared statement did not exist (No Reset On Close=true évite ce problème), et après une migration qui modifie le type d’une colonne, elles continuent d’échouer avec cached plan must not change result type, même sur de nouvelles connexions. Si vous avez besoin de requêtes préparées, connectez-vous directement.
  • État de session : les paramètres définis avec SET, y compris search_path, ne sont pas conservés d’une transaction à l’autre. Utilisez plutôt SET LOCAL au sein d’une transaction. PgBouncer rejette les mots-clés de chaîne de connexion Search Path et Options avec l’erreur unsupported startup parameter ; Timezone et Application Name fonctionnent.
  • Migrations : dotnet ef database update fonctionne également via PgBouncer, car le verrou de migration est un verrou de table qui est libéré à la fin de sa transaction.
  • Vérification TLS : pg_stat_ssl décrit la connexion entre PgBouncer et Postgres ; /db/tls renvoie donc none. La connexion de votre application à PgBouncer reste néanmoins vérifiée : un certificat de CA incorrect provoque le même échec.

Étapes suivantes

  • Connexion : chaînes de connexion, PgBouncer et TLS
  • Paramètres : paramètres Postgres et PgBouncer, comme max_connections
  • Répliques en lecture : envoyer des requêtes en lecture seule vers une réplique
  • Sécurité : listes d’accès IP et réseau privé
Dernière modification le 14 octobre 2026