Technique6 min de lecture

Query et QueryBuildDataSource en X++ : exemples de requêtes dynamiques

Construire une requête dynamique en X++ : Query, QueryBuildDataSource, QueryBuildRange, liens et QueryRun. Exemples Microsoft Learn et erreurs fréquentes.

La réponse courte

Une requête dynamique X++ se construit avec le modèle objet Query : un objet Query, des sources de données QueryBuildDataSource (une source enfant d'une autre crée une jointure), des plages QueryBuildRange (traduites en clause WHERE), des liens QueryBuildLink entre sources, puis QueryRun pour exécuter la requête et parcourir les résultats.

On l'utilise quand la requête doit être modifiable par l'utilisateur (boîte de dialogue d'un batch ou d'un état), réutilisée par un framework (suivi des modifications, data provider) ou construite selon des paramètres. Pour une simple lecture codée en dur, un select X++ reste plus lisible. Microsoft propose aussi l'API SysDa pour des requêtes extensibles sans le surcoût de QueryRun.

Les classes du modèle Query

  • Query : le haut de la définition, avec une ou plusieurs sources de données.
  • QueryBuildDataSource : l'accès à une source. Deux sources au même niveau produisent des requêtes SQL séparées ; une source enfant crée une jointure.
  • QueryBuildFieldList : les champs retournés (tous par défaut), avec agrégats possibles (SUM, COUNT, AVG).
  • QueryBuildRange : une restriction sur un champ, traduite en WHERE.
  • QueryBuildLink : la relation entre deux sources jointes (sur la source enfant).
  • QueryBuildDynalink : un lien vers un enregistrement externe, utilisé notamment par les formulaires synchronisés.
  • QueryRun : exécute la requête et récupère les données.

Exemple : jointures, plage et liens

Exemple de Microsoft Learn (requête de suivi des modifications) : clients, parties, adresse principale.

public static Query defaultCTQuery()
{
    Query q = new Query();

    QueryBuildDataSource custDs = q.addDataSource(tableNum(CustTable));

    QueryBuildDataSource partyDs = custDs.addDataSource(tableNum(DirPartyTable));
    partyDs.relations(true);

    QueryBuildDataSource locationDs = partyDs.addDataSource(tableNum(DirPartyLocation));
    locationDs.addRange(fieldNum(DirPartyLocation, IsPrimary)).value(queryValue(NoYes::Yes));
    locationDs.addLink(fieldNum(DirPartyTable, RecId), fieldNum(DirPartyLocation, Party));

    return q;
}

relations(true) utilise les relations définies sur les tables ; addLink précise explicitement les champs de jointure ; queryValue convertit une valeur en chaîne de plage. Pour parcourir les résultats :

QueryRun queryRun = new QueryRun(query);

while (queryRun.next())
{
    CustTable custTable = queryRun.get(tableNum(CustTable));
    // ...
}

Erreurs fréquentes

  • Ajouter deux sources au même niveau en pensant faire une jointure : ce sont deux requêtes séparées.
  • Construire une plage par concaténation de texte sans queryValue : risque d'erreur sur les caractères spéciaux.
  • Dans un formulaire, ajouter une plage après super() dans executeQuery : règle BP BPCheckinvalidExecuteQuery.
  • Utiliser QueryRun pour une lecture simple et fixe : un select est plus clair, ou SysDa si l'extensibilité compte.
  • Oublier relations(true) ou addLink : jointure produit cartésien.

Faire générer ce développement

Requêtes dynamiques de batch, d'état ou de data provider : un code répétitif, que l'IA génère bien quand le contexte est fourni. Skalp AI rédige la spécification, génère le code X++ et les tests unitaires, compile en contrôlant les bonnes pratiques, puis livre par pull request dans votre Azure DevOps : rien n'est fusionné sans la validation de votre architecte technique. Voir développement X++ par IA, 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).

À lire aussi : champ calculé dans une data entity.

Sources

Questions fréquentes

Comment faire une jointure avec QueryBuildDataSource ?

Ajoutez la seconde source comme enfant de la première (parentDs.addDataSource(...)), puis relations(true) ou addLink pour préciser les champs.

Query ou select en X++ ?

Select pour une lecture fixe et lisible ; Query quand la requête doit être modifiable par l'utilisateur ou construite dynamiquement. SysDa pour des requêtes extensibles sans surcoût.

À quoi sert queryValue ?

À convertir une valeur (énumération, date, texte) en chaîne correctement formatée pour une plage de requête.

Prêt à transformer votre D365 ?

Rejoignez les DSI qui développent leurs tickets D365 en 2 à 4 h pour 1 crédit (≈ 400 € en Basic, 200 € en Pro).