Batch SysOperation en X++ : écrire un traitement pas à pas
Batch SysOperation D365 F&O : classes Contract, Service, Controller et menu action. Code X++ d'exemple, reprises automatiques et erreurs fréquentes.
La réponse courte
Un traitement par lots avec le framework SysOperation repose sur trois classes et un élément de menu : une classe Contract (les paramètres, affichés automatiquement dans la boîte de dialogue), une classe Service (la logique métier), un Controller qui hérite de SysOperationServiceController (il relie le service, la méthode et le mode d'exécution), et un élément de menu action qui pointe vers le Controller. L'utilisateur lance alors le traitement immédiatement ou le planifie en batch depuis la boîte de dialogue.
SysOperation sépare paramètres, logique et exécution, là où l'ancien modèle RunBaseBatch mélangeait tout dans une seule classe. C'est aussi sur lui que s'appuie la fonctionnalité « real async » de Microsoft.
Étape 1 : la classe Contract
Exemple : purger un journal d'intégration personnalisé (table MyIntegrationLog) avant une date donnée. Le Contract porte un seul paramètre, la date limite. Chaque méthode parm décorée avec DataMemberAttribute devient un champ de la boîte de dialogue.
[DataContractAttribute]
class MyPurgeLogContract
{
TransDate cutOffDate;
[DataMemberAttribute('CutOffDate')]
public TransDate parmCutOffDate(TransDate _cutOffDate = cutOffDate)
{
cutOffDate = _cutOffDate;
return cutOffDate;
}
}Étape 2 : la classe Service
La méthode de service reçoit le Contract en paramètre. Ici, un delete_from supprime toutes les lignes concernées en une seule instruction SQL, au lieu d'une boucle qui supprimerait ligne par ligne : voir notre article sur insert_recordset, update_recordset et delete_from.
class MyPurgeLogService extends SysOperationServiceBase
{
public void process(MyPurgeLogContract _contract)
{
MyIntegrationLog log;
TransDate cutOffDate = _contract.parmCutOffDate();
ttsbegin;
delete_from log
where log.LogDate < cutOffDate;
ttscommit;
}
}Étape 3 : le Controller et l'élément de menu
Le Controller hérite de SysOperationServiceController. Son constructeur reçoit le nom de la classe de service, le nom de la méthode et le mode d'exécution ; la méthode main transmet les arguments et lance l'opération.
class MyPurgeLogController extends SysOperationServiceController
{
public static void main(Args _args)
{
MyPurgeLogController controller = new MyPurgeLogController(
classStr(MyPurgeLogService),
methodStr(MyPurgeLogService, process),
SysOperationExecutionMode::Synchronous);
controller.parmArgs(_args);
controller.startOperation();
}
}Créez ensuite un élément de menu action (ObjectType = Class, Object = MyPurgeLogController), ajoutez-le à un privilège rattaché à un rôle, puis au menu du module. Dans la boîte de dialogue, l'onglet de traitement en arrière-plan permet de planifier l'exécution en batch (récurrence, groupe de batch).
Reprises, versions de paramètres et « real async »
Trois points documentés par Microsoft Learn :
- Reprises : le champ « Maximum retries » d'une tâche batch relance la tâche en cas d'erreur ou de redémarrage du serveur batch. Pour les erreurs SQL transitoires, implémentez l'interface BatchRetryable (méthode isRetryable) sur le Controller, ou positionnez parmIdempotent(true) sur le batchInfo. N'activez cela que si le traitement peut être rejoué sans effet de bord ; c'est le cas d'une purge par date.
- Versions de paramètres : si vous ajoutez un paramètre à une classe dont les paramètres sont sérialisés (pack/unpack), gérez les anciennes versions pour éviter l'erreur « An error occurred while unpacking parameters for batch job ».
- Real async : une fonctionnalité (en preview) permet d'exécuter certaines opérations SysOperation de façon asynchrone sans bloquer l'utilisateur, en surchargeant canRunAsRealAsync et getSysRealAsyncOperationId dans le Controller.
Erreurs fréquentes
- Mettre la logique métier dans le Controller : elle doit rester dans le Service, testable séparément.
- Oublier DataMemberAttribute sur une méthode parm : le paramètre n'apparaît pas dans la boîte de dialogue et n'est pas sérialisé.
- Boucler avec while select … delete() sur des milliers de lignes au lieu d'un delete_from.
- Marquer un traitement non rejouable comme BatchRetryable ou idempotent : une reprise peut alors créer des doublons.
- Oublier le privilège sur l'élément de menu : le traitement existe mais personne ne peut le lancer.
- Ne pas versionner les paramètres après une évolution : les batchs déjà planifiés échouent au dépaquetage.
Faire générer le batch
Contract, Service, Controller, menu, privilège : le schéma est répétitif et se prête bien à la génération. Skalp AI analyse le contexte ERP, rédige la spécification, génère le code X++ et les tests unitaires, puis livre sur votre Azure DevOps pour validation par votre DSI. Voir traitements batch et SysOperation D365 F&O, le cadre général dans développer en X++ sans consultant en 2026, et les offres Basic, Pro et Max (1 crédit, ≈ 400 € en Basic, 200 € en Pro, consommé seulement à la génération du code).
Sources
- Microsoft Learn, « Enable batch retries », mise à jour du 13/03/2026, consultée le 11/10/2026.
- Microsoft Learn, « Batch parameter versioning », mise à jour du 13/03/2026, consultée le 11/10/2026.
- Microsoft Learn, « Real async feature enhancements », mise à jour du 30/03/2026, consultée le 11/10/2026.
- Microsoft Learn (Dynamics AX 2012, référence du framework), « SysOperationServiceController Class) », consultée le 11/10/2026.
Questions fréquentes
SysOperation ou RunBaseBatch ?
Pour un nouveau développement, SysOperation : il sépare paramètres, logique et exécution, et c'est sur lui que s'appuient des fonctionnalités récentes comme le « real async ». RunBaseBatch reste présent dans beaucoup de code existant.
Comment rendre un batch SysOperation rejouable après une erreur SQL ?
Implémentez BatchRetryable (isRetryable renvoie true) sur le Controller, ou appelez batchInfo().parmIdempotent(true). Le traitement doit pouvoir être rejoué sans créer de doublons.
Pourquoi « An error occurred while unpacking parameters for batch job » ?
Les paramètres sérialisés d'un batch planifié ne correspondent plus à la version actuelle de la classe. Microsoft recommande de versionner la liste des paramètres et de gérer chaque version dans unpack.
Prêt à transformer votre D365 ?
Rejoignez les DSI qui développent leurs tickets D365 en 1h pour 1 crédit (≈ 400 € en Basic, 200 € en Pro).