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'OperationCanceledException porte 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), savepoints Save/Rollback/Release et leurs équivalents asynchrones. Le commitment control IBM i suppose des tables journalisées : CREATE SCHEMA journalise automatiquement, CRTLIB non.
  • 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, NTiCommandException expose 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 avec NTiProgramParameter, 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 par Append chaînés. La lecture du buffer de sortie se fait elle aussi de façon typée, avec GetString, GetInt, GetShort, GetPackedDecimal, GetZonedDecimal, GetBytes ou GetDTSTimestamp. 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, Integer ou IntegerAndErrno (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=true bascule 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). AdditionalFactorCallback reste disponible, à titre d'ancienne API conservée par souci de compatibilité.
  • Chaîne de connexion : persist security info=false par défaut, le mot de passe est expurgé de ConnectionString dè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 ?

Reconnexion au serveur...

La connexion au serveur a été perdue. La page va se recharger.