mth_EnregistrerTableau
Persiste en base tous les éléments du tableau interne m_tabResults en une seule transaction. Mélange libre d'INSERT, UPDATE et DELETE dans le même lot. Les INSERT peuvent être exécutés en mode batch (INSERT_Multi performant) ou en mode unitaire (récupération de l'ID auto-incrément).
📋 Description
mth_EnregistrerTableau persiste en une seule transaction tous les éléments présents dans m_tabResults. Pour chaque élément, l'opération SQL effectuée est déterminée par l'état de sa clé primaire — exactement la même convention de signe que mth_Enregistrer, mais appliquée en lot :
| État de la PK | Opération | Mode d'exécution |
|---|---|---|
= 0 | INSERT | Batch ou unitaire selon p_bRécupérationID. PK auto-incrémentée par la base. |
> 0 | UPDATE | Toujours unitaire. Mise à jour de l'enregistrement existant. |
< 0 | DELETE | Toujours unitaire. Suppression de Abs(PK) avec cascade applicative. |
Trois avantages qu'une boucle manuelle ne peut pas reproduire facilement :
• Une seule transaction pour tout le lot : tout réussit ou rien n'est conservé. Pas de risque d'état partiel en base.
• Mode batch INSERT_Multi pour les nouveaux enregistrements : les INSERT sont regroupés en requêtes INSERT_Multi qui sont entre 10 et 100× plus rapides qu'une série d'INSERT unitaires (gain croissant avec le volume).
• Auto-positionnement des colonnes framework : SQL_INSERTED, SQL_ID_USER_INSERT, SQL_IP_USER, SQL_EXE, SQL_PROCEDURE_INSERT, SQL_STATUS, SQL_UUID sont alimentés automatiquement quand ils sont vides.
🔑 Signature
LOCAL bOptimisationUpdate est un booléen = Faux,
LOCAL sCallbackProgression est une chaîne = ""
) : (booléen, entier, chaîne)
| Élément | Valeur |
|---|---|
| Visibilité | PUBLIQUE |
Paramètres
| Paramètre | Type | Défaut | Rôle |
|---|---|---|---|
bOptimisationUpdate | booléen | Faux | Si Vrai, ne traite que les éléments en UPDATE marqués comme modifiés (p_bUpdated = Vrai). INSERT et DELETE restent toujours exécutés quel que soit ce paramètre. Voir §05. |
sCallbackProgression | chaîne | "" | Nom d'une procédure projet appelée à chaque itération avec la position courante et la taille totale. Utile pour mettre à jour une jauge IHM. Voir §06. |
🔁 Comportement par élément
La méthode itère sur m_tabResults. Pour chaque élément, elle détermine l'opération à effectuer selon la convention de signe de la PK (identique à mth_Enregistrer). Un même tableau peut donc contenir un mélange libre d'INSERT, UPDATE et DELETE, traités en une seule passe.
Auto-positionnement des colonnes framework lors d'un INSERT
Pour chaque élément en INSERT, si les colonnes framework suivantes sont vides ou à zéro, elles sont alimentées automatiquement avant l'écriture :
| Colonne | Valeur attribuée si vide |
|---|---|
SQL_INSERTED | Date / heure courante (si bHorodatageAuto activé sur la classe) |
SQL_ID_USER_INSERT | ID de l'utilisateur courant (depuis la session) |
SQL_IP_USER | Identifiant du poste de travail courant |
SQL_EXE | Nom de l'exécutable en cours |
SQL_PROCEDURE_INSERT | Nom de la procédure démarreuse de la transaction |
SQL_STATUS | DATA_ACCESSIBLE par défaut |
SQL_UUID | UUID auto-généré (préfixe session + GUID brut 256 bits) |
Si une colonne framework a déjà été positionnée par l'appelant (cas d'un import qui veut préserver les valeurs d'origine, par exemple), la valeur fournie est conservée.
Le couple PK / p_bNouvelEnregistrement permet de couvrir le cas particulier de l'import avec ID imposé — utile pour les migrations entre bases ou les restaurations qui doivent préserver les identifiants d'origine.
Quand p_bNouvelEnregistrement = Vrai sur un élément dont la PK est déjà renseignée (PK > 0), la méthode considère que l'opération est un INSERT et non un UPDATE. La PK fournie est conservée telle quelle dans la base au lieu d'être attribuée par auto-incrément.
Tableau récapitulatif complet :
PK = 0 · p_bNouvelEnregistrement = Faux/Vrai → INSERT auto-incrément
PK > 0 · p_bNouvelEnregistrement = Faux → UPDATE
PK > 0 · p_bNouvelEnregistrement = Vrai → INSERT avec ID imposé (import)
PK < 0 · (peu importe) → DELETE de Abs(PK)
Lors d'un DELETE en lot via la convention PK<0, l'élément du tableau interne m_tabResults reste présent après la suppression réussie en base. Ses membres mappés conservent les valeurs antérieures, mais le drapeau p_bRecordDeleted (alias français : p_bEnregistrementSupprimé) est positionné à Vrai pour signaler que cet élément représente un enregistrement supprimé.
Ce comportement est volontaire : il permet de continuer à exploiter le tableau après l'enregistrement (calculs, exports, journalisation) sans devoir recharger les données depuis la base. Les méthodes d'agrégat (mth_SommeValeurs, mth_ValeurMoyenne, mth_ValeurMaximale, mth_ValeurMinimale, mth_ValeursDistinctes, mth_Regroupement) excluent automatiquement les éléments marqués supprimés du calcul.
Pour purger physiquement le tableau des éléments supprimés, l'appelant doit le faire explicitement via TableauSupprime ou recharger les données depuis la base.
⚡ Modes d'exécution : batch vs unitaire
Pour les INSERT, la méthode propose deux modes d'exécution. Le choix se fait par élément via le flag p_bRécupérationID positionné sur l'objet :
p_bRécupérationID | Mode | Comportement |
|---|---|---|
Faux (défaut) | BATCH | Les INSERT sont regroupés en requêtes INSERT_Multi et envoyés à la base par paquets. Très performant sur les gros volumes. En contrepartie, la PK auto-incrémentée n'est pas répercutée sur l'objet. |
Vrai | UNITAIRE | Chaque INSERT est exécuté individuellement (équivalent à mth_Enregistrer par élément). L'ID auto-incrément est récupéré et écrit dans la PK de l'objet, utilisable ensuite côté appelant. |
Les UPDATE et les DELETE sont toujours exécutés en mode unitaire, indépendamment de la valeur de p_bRécupérationID. Le batch ne s'applique qu'aux INSERT.
Activer ce flag sur un élément si vous avez besoin, après l'enregistrement, de l'ID auto-incrément de cet enregistrement. Cas typiques :
• Création d'enregistrements liés dans un second temps (ex : créer un client puis ses commandes liées)
• Construction d'un référentiel ID → entité côté appelant
• Renvoi de l'ID au client web / mobile / API
Dans le cas inverse (import en masse, peuplement de référentiel sans réutilisation immédiate), laisser le mode batch (Faux) qui est nettement plus rapide.
Si la session ORM_CSHX2 fonctionne en mode metadata METADATA_MODE_JOIN (Mode 3), p_bRécupérationID est forcé à Vrai automatiquement sur tous les éléments en INSERT, car l'ID est requis par le framework pour l'INSERT metadata associé. Ce comportement est transparent pour l'appelant — pas d'action à entreprendre.
Taille des paquets en mode batch — p_NombreInsertSimultanés
En mode batch, les INSERT sont regroupés en paquets envoyés à la base par requêtes INSERT_Multi. La taille de ces paquets est paramétrable via la propriété publique p_NombreInsertSimultanés (getter / setter) :
Valeur par défaut : 250. Compromis raisonnable entre vitesse d'envoi et limites pratiques des moteurs SQL (taille des paquets réseau, nombre maximal de paramètres autorisés par requête, mémoire serveur consommée par le buffer SQL). Augmenter la valeur peut accélérer un import sur de très gros volumes ; la diminuer peut être nécessaire si la connexion ou le serveur impose une limite plus stricte sur la taille des requêtes.
• Augmenter (500, 1000…) : import volumineux sur un réseau performant, gain mesurable au-delà du seuil par défaut.
• Diminuer (50, 100) : connexion réseau lente ou peu fiable (timeouts à éviter), serveur SQL avec une limite stricte sur la taille des paquets, base partagée où l'on veut éviter de monopoliser la connexion sur de longues requêtes.
• Garder 250 : dans tous les autres cas. La valeur par défaut est calibrée pour fonctionner sans surprise sur la plupart des configurations MySQL · MariaDB · PostgreSQL.
🎯 Optimisation par flag p_bUpdated
Quand un tableau contient des dizaines ou des centaines d'enregistrements et que seuls quelques-uns ont été modifiés, parcourir et réécrire l'ensemble est inutile. Le paramètre bOptimisationUpdate = Vrai permet de filtrer côté framework :
| Élément | bOptimisationUpdate = Faux (défaut) | bOptimisationUpdate = Vrai |
|---|---|---|
| INSERT (PK = 0) | Traité | Toujours traité |
| DELETE (PK < 0) | Traité | Toujours traité |
UPDATE (PK > 0) avec p_bUpdated = Vrai | Traité | Traité |
UPDATE (PK > 0) avec p_bUpdated = Faux | Traité | ⚡ Ignoré |
Le flag p_bUpdated est positionné automatiquement sur un objet dès qu'un de ses membres mappés est modifié. Le code appelant n'a donc rien à gérer manuellement : les UPDATE qui n'ont rien à mettre à jour seront simplement passés au lieu d'émettre un UPDATE SQL inutile.
Activer dans tout flux où le tableau contient une majorité d'éléments inchangés et une minorité d'éléments modifiés. Cas typiques :
• Édition d'une grille (tableau de saisie) où l'utilisateur ne modifie que quelques lignes
• Synchronisation de référentiel où la plupart des entrées sont déjà à jour
• Recalcul partiel d'un état métier
Laisser à Faux (défaut) si tous les éléments sont systématiquement à réécrire (réinitialisation, recalcul complet…).
Le filtrage bOptimisationUpdate ne s'applique qu'aux UPDATE. Un INSERT (PK = 0) ou un DELETE (PK < 0) sont des opérations intentionnellement explicites de l'appelant : ils sont toujours exécutés, indépendamment de p_bUpdated. C'est un choix de design qui évite qu'un INSERT ou un DELETE oublié reste silencieusement non appliqué.
📊 Callback de progression
Pour les traitements longs (gros volumes, IHM avec jauge), le paramètre sCallbackProgression permet de désigner une procédure projet qui sera appelée à chaque itération avec la position courante et la taille totale du tableau.
Signature de la procédure callback
Côté appel, transmettre simplement le nom de la procédure dans sCallbackProgression :
Le callback de progression est appelé uniquement quand le code s'exécute depuis le composant externe ORM_CSHX2 sur cible ApplicationWindows. Dans les autres contextes — service, web-service, projet WinDev classique non-composant, mobile — le paramètre est ignoré silencieusement et la méthode s'exécute normalement sans appeler le callback.
Cette restriction est volontaire : un service ou un web-service n'a pas d'IHM à rafraîchir, et appeler un callback dans ces contextes aurait un coût sans bénéfice.
🔄 Transaction automatique
La méthode ouvre une seule transaction au début du traitement et la valide à la fin si tout s'est bien déroulé, ou l'annule en cas d'erreur. Ce comportement garantit que l'intégralité du tableau est traitée de façon atomique : tout réussit ou rien n'est conservé en base.
Si une erreur survient pendant le traitement (verrouillage, contrainte SQL, etc.), la boucle s'interrompt immédiatement et la transaction est annulée. Aucune des modifications déjà appliquées au cours du lot n'est conservée.
Comme toutes les méthodes ORM_CSHX2, mth_EnregistrerTableau respecte le modèle owner : si une transaction est déjà active à l'appel, elle ne touche pas à la transaction et c'est l'appelant qui en est responsable. Détails dans ORM_Transactions.
💡 Exemples
Mode 1 — INSERT batch performant (sans récupération d'ID)
Cas d'usage : import d'une liste de produits dans une table catalogue, où l'on n'a pas besoin de réutiliser les IDs immédiatement.
Mode 2 — INSERT avec récupération des IDs (mode unitaire)
Cas d'usage : créer plusieurs enregistrements et conserver leurs IDs auto-incrémentés pour les réutiliser.
Mode 3 — Mix INSERT / UPDATE / DELETE en une seule passe
Cas d'usage : sauvegarde d'une grille de saisie où l'utilisateur a ajouté, modifié et supprimé des lignes. Tout est traité atomiquement.
Mode 4 — Optimisation pour grille avec peu de modifications
Cas d'usage : 200 lignes affichées, l'utilisateur en modifie 3. Sans optimisation, 200 UPDATE seraient émis. Avec bOptimisationUpdate = Vrai, seulement 3.
Mode 5 — Avec callback de progression
Cas d'usage : import de 10 000 lignes avec une jauge utilisateur dans le composant externe.
Mode 6 — Import avec IDs imposés (cas avancé)
Cas d'usage : migration depuis une base externe en préservant les IDs d'origine.
Mode 7 — Ajuster la taille des paquets en mode batch
Cas d'usage : import de plusieurs centaines de milliers de lignes sur un réseau performant, où l'on veut maximiser le débit en augmentant la taille des paquets INSERT_Multi.
Mode 8 — Diagnostic via mode verbose
Pour visualiser le détail des requêtes émises (BEGIN, INSERT_Multi, UPDATE individuels, DELETE en cascade, COMMIT) :
Détails complets : ORM_VerboseMode.