Migration du code d'accès aux données .NET d'Oracle vers PostgreSQL
Migrer la couche d'accès aux données C# d'un projet en copie .Postgres d'Oracle (Oracle.ManagedDataAccess) vers PostgreSQL (Npgsql). Traiter élément par élément via Reports/{ProjectName}/MigrationChecklist.md.
Prérequis
- La copie du projet
.Postgresexiste (créée lors de la configuration de Phase 5). Reports/{ProjectName}/MigrationChecklist.mdexiste et est la source de vérité pour ce qu'il faut modifier.Reports/{ProjectName}/OracleRiskAnalysis.mdexiste pour croiser les différences de comportement.
Workflow
Progression :
- [ ] Étape 1 : Remplacer les packages NuGet
- [ ] Étape 2 : Mettre à jour la configuration de la chaîne de connexion
- [ ] Étape 3 : Réécrire les références de type ADO.NET
- [ ] Étape 4 : Corriger les mappages DbType
- [ ] Étape 5 : Migrer l'invocation de procédures stockées
- [ ] Étape 6 : Adresser le SQL et la syntaxe spécifiques à Oracle
- [ ] Étape 7 : Compiler et vérifier
Étape 1 : Remplacer les packages NuGet
Dans le .csproj du projet .Postgres :
- Supprimer :
Oracle.ManagedDataAccess.Core,Oracle.EntityFrameworkCore(et tout autre packageOracle.*) - Ajouter :
Npgsql(pour ADO.NET) et/ouNpgsql.EntityFrameworkCore.PostgreSQL(pour EF Core) - Conserver le versioning cohérent avec la version .NET cible ; ne pas introduire de versions de package plus récentes que celles déjà utilisées par la solution pour des packages similaires.
- Si des abstractions
System.Data(IDbConnection,IDbCommand) sont utilisées au niveau du projet, le code de surface peut nécessiter moins de modifications — identifiez-les en premier.
Étape 2 : Mettre à jour la configuration de la chaîne de connexion
- Localiser la chaîne de connexion Oracle dans
appsettings.json,appsettings.{env}.json,web.config,app.config, ou la configuration via variables d'environnement. - Remplacer par une chaîne de connexion compatible Npgsql :
Host=localhost;Port=5432;Database=mydb;Username=myuser;Password=mypassword - Ne pas coder en dur les identifiants — utiliser le même mécanisme de configuration déjà en place (par ex. variables d'environnement, gestionnaire de secrets,
IConfiguration). - Mettre à jour les clés de chaîne de connexion nommées uniquement si elles étaient spécifiques à Oracle (par ex.
OracleConnection). Privilégier le maintien du même nom de clé pour minimiser les changements de configuration d'application.
Étape 3 : Réécrire les références de type ADO.NET
Remplacer les types ADO.NET spécifiques à Oracle par leurs équivalents Npgsql :
| Type Oracle | Remplacement Npgsql |
|---|---|
OracleConnection |
NpgsqlConnection |
OracleCommand |
NpgsqlCommand |
OracleDataReader |
NpgsqlDataReader |
OracleDataAdapter |
NpgsqlDataAdapter |
OracleParameter |
NpgsqlParameter |
OracleTransaction |
NpgsqlTransaction |
OracleException |
NpgsqlException |
OracleDbType |
NpgsqlDbType (de l'espace de noms NpgsqlTypes) |
Mettre à jour les directives using en conséquence (using Oracle.ManagedDataAccess.Client → using Npgsql).
Si le code utilise des abstractions IDbConnection/IDbCommand enregistrées via l'injection de dépendances, mettre à jour uniquement l'enregistrement DI et la chaîne de connexion — le code consommateur peut ne pas avoir besoin de changements.
Étape 4 : Corriger les mappages DbType et NpgsqlDbType
Les types de paramètre Oracle ne correspondent pas 1:1 à Npgsql. Examiner chaque OracleParameter (à présent NpgsqlParameter) qui définit un type explicite :
| Type Oracle | Notes |
|---|---|
OracleDbType.Varchar2 |
Utiliser NpgsqlDbType.Varchar ou omettre (Npgsql déduit de la valeur) |
OracleDbType.Clob |
Utiliser NpgsqlDbType.Text |
OracleDbType.Number |
Utiliser NpgsqlDbType.Numeric ou NpgsqlDbType.Integer selon la précision |
OracleDbType.Date |
Utiliser NpgsqlDbType.Date (date seulement) ou NpgsqlDbType.Timestamp (si composante temporelle utilisée) |
OracleDbType.TimeStamp |
Utiliser NpgsqlDbType.Timestamp |
OracleDbType.RefCursor |
Utiliser NpgsqlDbType.Refcursor — voir Étape 5 |
OracleDbType.Char |
Utiliser NpgsqlDbType.Char |
Pour les paramètres où Oracle déduit le type de la valeur, Npgsql déduit également — la définition explicite du type est souvent inutile et peut être supprimée.
Étape 5 : Migrer l'invocation de procédures stockées
L'invocation de procédures stockées diffère considérablement entre Oracle et PostgreSQL :
- Type de commande : Conserver
CommandType.StoredProcedurepour les appels de fonction. Pour les procédures qui utilisent des paramètresOUT, PostgreSQL nécessiteCommandType.Textavec la syntaxeCALL proc_name(...)dans certaines versions de Npgsql — vérifier par rapport à la version cible de Npgsql. - Gestion de RefCursor : Oracle retourne des ref cursors comme paramètres de sortie ; PostgreSQL les retourne différemment :
- Pour
RETURNS TABLE/RETURNS SETOF, utiliserExecuteReader()directement — aucun paramètre cursor nécessaire. - Pour
RETURNS refcursor, appeler dans une transaction, lire le nom du cursor du paramètre de sortie, puis émettreFETCH ALL IN "<cursor_name>". - Supprimer tout code d'enveloppe de cursor spécifique à Oracle (par ex.
OracleRefCursor).
- Pour
- Paramètres OUT : Les procédures stockées PostgreSQL utilisent
INOUTou les valeurs de retour de fonction. Vérifier que la direction du paramètre correspond à la signature de procédure migrée. - Séquence
NEXTVAL: RemplacerSELECT {SEQUENCE}.NEXTVAL FROM DUALparSELECT nextval('{sequence_name}'). - Paramètres nommés : Npgsql utilise
@param_name; Oracle utilisait:param_name. Mettre à jour tous les préfixes de nom de paramètre.
Étape 6 : Adresser les constructions spécifiques à Oracle et les motifs C#
Examiner les chaînes SQL en ligne et les générateurs de requête pour les constructions spécifiques à Oracle et les remplacer :
| Construct Oracle | Remplacement PostgreSQL |
|---|---|
ROWNUM <= n |
LIMIT n |
ROWNUM = 1 |
LIMIT 1 |
NVL(x, y) |
COALESCE(x, y) |
DECODE(expr, v1, r1, ...) |
CASE WHEN expr = v1 THEN r1 ... END |
SYSDATE / SYSTIMESTAMP |
NOW() ou CURRENT_TIMESTAMP |
TO_CHAR(date, fmt) |
TO_CHAR(date, fmt) (généralement compatible ; vérifier les chaînes de format) |
TO_DATE(str, fmt) |
TO_DATE(str, fmt) (vérifier les chaînes de format) |
TO_NUMBER(str) |
CAST(str AS NUMERIC) ou str::NUMERIC |
|| concaténation de chaîne |
|| (compatible) |
Table DUAL |
Supprimer FROM DUAL ; PostgreSQL évalue SELECT expr sans table |
Hiérarchie CONNECT BY |
Réécrire en utilisant des CTEs récursives (WITH RECURSIVE) |
MERGE INTO |
Réécrire comme INSERT ... ON CONFLICT DO UPDATE |
Chaîne vide '' comme NULL |
Oracle traite '' comme NULL ; PostgreSQL ne le fait pas — vérifier les comparaisons et les gardes IS NULL |
VARCHAR2 |
VARCHAR ou TEXT |
Étape 7 : Compiler et vérifier
Après avoir traité tous les éléments de la liste de contrôle :
- Exécuter
dotnet buildsur le projet.Postgres. Corriger les erreurs de compilation restantes. - Vérifier qu'aucun espace de noms spécifique à Oracle ne demeure : rechercher
Oracle.ManagedDataAccess,OracleConnection,OracleCommand, motifs:param. - Marquer les éléments complétés dans
Reports/{ProjectName}/MigrationChecklist.md.
Projets EF Core
Si le projet utilise Oracle.EntityFrameworkCore :
- Remplacer l'enregistrement du fournisseur dans la configuration
DbContext:.UseOracle(...)→.UseNpgsql(...) - Remplacer les références
OracleDbContextOptionsBuilder. - Examiner
OnModelCreatingpour les configurations spécifiques à Oracle (par ex.HasColumnType("NUMBER")→HasColumnType("numeric")). - Configuration de séquence : la syntaxe
modelBuilder.HasSequence<int>("seq_name").StartsAt(1).IncrementsBy(1)est compatible ; vérifier les valeurs par défaut de colonne référençant des séquences. - Ne pas exécuter les migrations EF Core — le schéma est géré en externe via des scripts DDL (Phase 4).
Contraintes clés
- Travailler uniquement au sein de la copie
.Postgres— ne jamais modifier le projet original ciblant Oracle. - S'en tenir aux versions .NET et C# existantes ; ne pas introduire de fonctionnalités de langage ou de runtime plus récentes.
- Préserver les commentaires et la logique d'application ; modifier uniquement ce qui est nécessaire pour la compatibilité PostgreSQL.
- Oracle est la source de vérité — les différences de comportement doivent être documentées comme rapports de bug, pas modifiées silencieusement.