Vue d'ensemble
Introduction
NTi Data Provider est le fournisseur d'accès 100 % managé d'AUMERIAL pour IBM i (AS/400, iSeries) : il connecte n'importe quelle application .NET à DB2 for i et aux ressources natives du système, sans driver ODBC, sans OLE DB, sans IBM i Access, sans aucun composant à installer côté client :
- SQL synchrone et asynchrone : implémentation ADO.NET stricte, avec un asynchrone réel de bout en bout (de
OpenAsyncàDisposeAsync) - Commandes CL : exécution directe, avec la pile de messages du serveur en cas d'erreur
- Appels de programmes : RPG, CL, COBOL et API système, avec paramètres typés
- Programmes de service : appel des procédures exportées via QZRUCLSP
- Entity Framework Core 8, 9 et 10 : via le package compagnon
Aumerial.EntityFrameworkCore - MFA : facteur d'authentification additionnel (TOTP IBM i), y compris en asynchrone
- Pool de connexions : pool unique et générique, identité client incluse dans la clé de pool
- TLS : chiffrement des services hôtes avec validation de la chaîne de certificats par défaut
Remarque :
Le modèle de programmation est celui qu'un développeur .NET connaît déjà : NTi implémente le contrat ADO.NET standard (voir la documentation ADO.NET de Microsoft) et cette documentation se concentre sur ce qui est spécifique à NTi et à l'IBM i.
100 % managé : partout où .NET s'exécute
NTi est écrit intégralement en code managé, sans la moindre dépendance native, jusque dans ses conversions de texte : là où la plupart des providers s'appuient sur System.Text.Encoding.CodePages pour traduire l'EBCDIC, NTi embarque ses propres tables CCSID (EBCDIC, DBCS, Unicode), extraites d'un IBM i réel et contre-vérifiées face aux implémentations de référence.
L'assembly est AnyCPU : un seul binaire, aucune variante par architecture, aucun runtime natif à déployer. NTi fonctionne donc sur toutes les architectures où .NET s'exécute :
- x86 et x64 (Windows, Linux, macOS)
- ARM64 (Windows, Linux, macOS, y compris AWS Graviton et Apple Silicon)
- ppc64le avec .NET 8 ou ultérieur (Linux on Power, y compris sur la même machine que l'IBM i)
- s390x avec .NET 8 ou ultérieur (Linux on IBM Z)
Client lourd Windows, conteneur Linux, fonction serverless ARM64 ou partition Linux on Power voisine de l'IBM i : le même package s'exécute partout, sans recompilation.
Architecture : serveurs hôtes et deux jobs par connexion
NTi dialogue directement avec les serveurs hôtes de l'IBM i (host servers) en TCP/IP ou en TLS, en construisant lui-même les flux de données du protocole, sans jamais transmettre le mot de passe en clair :
| Usage | Serveur hôte | Job IBM i |
|---|---|---|
| Signon (authentification, à l'ouverture) | *SIGNON | QZSOSIGN |
| SQL (base de données) | *DATABASE | QZDASOINIT |
| Commandes CL et programmes | *RMTCMD | QZRCSRVS |
Le job signon ne sert qu'à l'ouverture, puis s'efface : chaque NTiConnection ouverte s'appuie ensuite, pour toute sa durée de vie, sur deux jobs IBM i distincts, celui du SQL et celui des commandes et programmes.
Cette séparation a une conséquence importante : les deux jobs ont chacun leur propre QTEMP et leur propre CURLIB. Un objet créé dans QTEMP par une commande CL n'est pas visible depuis le SQL, et réciproquement. Pour exécuter du CL dans le job SQL (et partager sa QTEMP), le pont SQL CALL QSYS2.QCMDEXC('...') reste disponible, au prix du passage par le moteur SQL. Les propriétés DatabaseJob et CommandJob de la connexion permettent d'identifier les deux jobs à tout moment (traçage, WRKJOB, débogage).
Le cycle de vie est entièrement maîtrisé : chaque connexion NTi porte ses sockets TCP, et la fermeture (Close, Dispose, DisposeAsync) termine proprement les jobs IBM i associés, sauf si le pool les conserve pour réutilisation. Fini les jobs QZDASOINIT « fantômes » qui s'accumulent côté serveur. Le transport lit toujours des trames complètes avant analyse : une erreur de parsing ne laisse jamais une connexion désynchronisée.
Les ports par défaut (8471, 8475, 8476, mappeur 449, variantes TLS 94xx) sont détaillés dans les Prérequis.
Les packages NTi
| Package | Version | Rôle |
|---|---|---|
Aumerial.Data.Nti |
5.0.0 | Le provider ADO.NET, objet de cette documentation. Une génération antérieure reste disponible pour les applications existantes, avec un contrat public inchangé : le code déjà écrit continue de compiler et de s'exécuter tel quel. |
Aumerial.EntityFrameworkCore |
8.5.0 9.5.0 10.5.0 |
Le provider Entity Framework Core. Le numéro majeur suit la version d'EF Core (8, 9 ou 10), le mineur 5 identifie la génération NTi sous-jacente. |
Fonctionnalités
Base de données (SQL)
NTi implémente le modèle ADO.NET complet, connexion, commande, lecteur, paramètres et adaptateur compris, avec transactions et métadonnées GetSchema à la clé.
- Asynchrone réel : la voie async ne fait aucune I/O synchrone, de
OpenAsync(pool, TCP/TLS, signon, MFA compris) jusqu'àDisposeAsync. L'annulation honore le jeton de l'appelant partout ; par contrat, annuler une opération en vol casse la connexion (l'OperationCanceledExceptionporte le jeton de l'appelant, la connexion doit être rouverte). - Paramètres : marqueurs positionnels
?ou nommés@name, jamais les deux dans une même commande. Dapper fonctionne sans adaptation. - Procédures stockées : paramètres d'entrée/sortie et procédures multi-result-sets, parcourues avec
NextResult. - LOB : BLOB, CLOB, DBCLOB et XML, en lecture directe ou par locators (voie async comprise).
- Transactions :
BeginTransaction(IsolationLevel)(ReadUncommitted à Serializable, ReadCommitted par défaut), savepointsSave/Rollback/Releaseet leurs équivalents asynchrones. Le commitment control IBM i suppose des tables journalisées :CREATE SCHEMAjournalise automatiquement,CRTLIBnon. - Types : tous les types DB2 for i, y compris packed/zoned decimal, DECFLOAT, GRAPHIC et FOR BIT DATA (restitué en binaire, jamais converti silencieusement).
Commandes CL et appels de programmes
Sans passer par SQL, sur le job QZRCSRVS dédié :
ExecuteClCommand/ExecuteClCommandAsync: exécute n'importe quelle commande CL. En cas d'échec,NTiCommandExceptionexpose la pile complète des messages du serveur (identifiant, gravité, texte, aide).CallProgram/CallProgramAsync: appelle des programmes RPG, CL ou COBOL. Les paramètres se construisent avecNTiProgramParameter, qui propose des constructeurs typés (CHAR avec CCSID, BINARY(2)/BINARY(4), packed/zoned decimal, octets bruts, tableaux) et permet de composer des structures de données parAppendchaînés. La lecture du buffer de sortie se fait elle aussi de façon typée, avecGetString,GetInt,GetShort,GetPackedDecimal,GetZonedDecimal,GetBytesouGetDTSTimestamp. Un récepteur vide (new NTiProgramParameter()) se redimensionne automatiquement sur la donnée réellement écrite par le programme, ce qui le rend idéal pour les retours VARCHAR et les API à récepteur variable.- Les API système (QUSROBJD, QUSLOBJ, etc.) s'appellent comme des programmes ordinaires.
Programmes de service (QZRUCLSP)
CallServiceProgram / CallServiceProgramAsync appellent les procédures exportées des programmes de service, via l'API système QZRUCLSP :
- Le nom d'export est sensible à la casse (interprété en CCSID 37 par défaut, paramétrable).
- Les paramètres passent par référence (défaut) ou par valeur (
ByValue, réservé aux BINARY(4) de 4 octets exactement), avec 7 paramètres au maximum. - Les valeurs de retour possibles sont
None,IntegerouIntegerAndErrno(valeur et errno lus dans le paramètre de retour). Le retour pointeur n'est pas supporté, un pointeur d'espace serveur n'ayant pas de sens côté client : les procédures qui produisent du texte le rendent plutôt via un buffer fourni par l'appelant.
Entity Framework Core
Le package Aumerial.EntityFrameworkCore prend en charge EF Core 8, 9 et 10 (voir la documentation EF Core) :
- LINQ et migrations idempotentes
ExecuteUpdate/ExecuteDelete- IDENTITY lues via FINAL TABLE
- Concurrence optimiste par ROW CHANGE TIMESTAMP
- Séquences HiLo
- Scaffolding des bases existantes (zoned/packed decimal, FOR BIT DATA, DECFLOAT, tables sans clé)
Le naming sql est requis (naming=sql, valeur par défaut de NTi), et le volet EF Core exige IBM i 7.2 ou ultérieur.
Sécurité
- Signon : mot de passe jamais transmis en clair, tous les niveaux QPWDLVL supportés.
- TLS :
ssl=truebascule les services hôtes sur leurs ports TLS. La chaîne de certificats est validée par défaut (untrusted=false), la levée de validation étant réservée aux environnements de test. - MFA : facteur additionnel TOTP de l'IBM i, fourni statiquement (
AdditionalFactor), par délégué (AdditionalFactorProvider) ou par délégué asynchrone honorant le jeton d'annulation (AdditionalFactorAsyncProvider).AdditionalFactorCallbackreste disponible, à titre d'ancienne API conservée par souci de compatibilité. - Chaîne de connexion :
persist security info=falsepar défaut, le mot de passe est expurgé deConnectionStringdès la connexion ouverte.
Pool de connexions
Le pool est unique et générique, inactif par défaut. Activez-le avec pooling=true, ce qui est fortement recommandé pour les charges web et services. La clé de pool ne contient jamais le mot de passe en clair, et elle intègre l'identité client (application name, client accounting, client user identifier, client program identifier), si bien que deux identités distinctes ne partagent jamais une connexion.
NTiConnection.ClearPool(connection) et NTiConnection.ClearAllPools() purgent les pools à la demande.
Mise en œuvre
Côté .NET, tout tient dans le package NuGet Aumerial.Data.Nti : aucune installation, aucun prérequis logiciel autre que le runtime .NET.
Côté IBM i, il faut des identifiants valides, les services TCP hôtes démarrés et une clé de licence installée dans la bibliothèque KNTI (licence d'essai gratuite de 30 jours disponible sur portal.aumerial.com).
Et maintenant ?
- Prérequis : versions IBM i et .NET, architectures, ports réseau
- Installation : licence, package NuGet et premier programme
- Guide de démarrage rapide : première connexion et premiers appels IBM i
- Connexion : chaîne de connexion, pool, MFA, TLS