Partager via


Résultats de page à l’aide de QueryExpression

Vous pouvez spécifier une limite au nombre de lignes récupérées pour chaque requête en définissant une taille de page. À l’aide de la pagination, vous pouvez récupérer des pages consécutives de données qui représentent tous les enregistrements correspondant aux critères d’une requête de manière performante.

La taille de page par défaut et maximale est de 5 000 lignes. Si vous ne définissez pas de taille de page, Dataverse renverra jusqu’à 5 000 lignes de données à la fois. Pour obtenir plus de lignes, vous devez envoyer des requêtes supplémentaires.

Notes

Modèles de pagination

Dataverse a deux modèles de pagination : simple et avec des cookies de pagination :

Simplicité

  • Utilise uniquement les propriétés QueryExpression.PageInfo Count et PageNumber
  • Convient uniquement aux petits jeux de données
  • Impossible de renvoyer un jeu de données supérieur à 50 000 enregistrements
  • Performances réduites à mesure que le nombre de lignes augmente

Cookies de pagination

Pagination simple

Vous pouvez demander l’accès à la première page en définissant la propriété QueryExpression.PageInfo avec une classe PagingInfo instance avec le PagingInfo.PageNumber à 1 et le PagingInfo.Count à la taille de la page avant d’envoyer la requête :

var query = new QueryExpression(entityName: "account")
{
      ColumnSet = new ColumnSet("name"),
      PageInfo = new PagingInfo() { 
         Count = 3,
         PageNumber = 1
      }
};
query.AddOrder(attributeName:"name",orderType: OrderType.Ascending);
query.AddOrder(attributeName: "accountid", orderType: OrderType.Ascending);

Pour obtenir les trois enregistrements suivants, incrémentez la valeur PageInfo.PageNumber et envoyez une autre requête.

query.PageInfo.PageNumber++;

Avec la pagination simple, parfois appelée Pagination héritée, Dataverse récupère tous les résultats de la requête jusqu’à la page actuelle, sélectionne le nombre d’enregistrements nécessaires pour la page, puis ignore le reste. Cela permet de reculer et d’avancer rapidement entre les données ou de passer à une page spécifique. Cependant, le nombre total d’enregistrements est limité à 50 000 et des problèmes de performances peuvent se produire pour les requêtes complexes et les résultats de requêtes distincts triés de manière arbitraire.

La pagination simple fonctionne bien pour les petits jeux de données, mais à mesure que le nombre de lignes dans le jeu de données augmente, les performances sont affectées. Pour de meilleures performances dans tous les cas, nous vous recommandons d’utiliser les cookies de pagination de manière cohérente.

Cookies de pagination

Lorsqu’il y a d’autres lignes à récupérer après avoir demandé la première page, Dataverse renvoie généralement un cookie de pagination à utiliser sur les requêtes suivantes pour les pages suivantes.

Le cookie de pagination contient des données sur le premier et le dernier enregistrement des résultats et permet Dataverse de récupérer la ligne de données suivante le plus rapidement possible. Un cookie de pagination doit être utilisé lorsqu’il est renvoyé par la page précédente. Vous ne devez pas modifier les données du cookie de pagination, définissez simplement la valeur sur la propriété QueryExpression.PageInfo.PagingCookie et incrémentez la QueryExpression.PageInfo.PageNumber valeur pour demandes ultérieures.

Requêtes qui ne prennent pas en charge les cookies de pagination

Certaines requêtes ne prennent pas en charge les cookies de pagination. Lorsque les cookies de pagination ne sont pas pris en charge par une requête, aucune valeur de cookie de pagination n’est renvoyée avec le résultat. Par exemple, les requêtes triées à l’aide d’une LinkEntity colonne peuvent ne pas prendre en charge les cookies de pagination.

Lorsque Dataverse ne renvoie pas de cookie de pagination, le modèle de pagination revient à la pagination simple, avec toutes les limitations qui l’accompagnent.

La méthode statique suivante RetrieveAll renverra tous les enregistrements qui correspondent à la requête QueryExpression , en envoyant plusieurs requêtes si le nombre d’enregistrements dépasse la taille de la page.

Après chaque requête, la méthode vérifie la propriété EntityCollection.MoreRecords pour déterminer si d’autres enregistrements correspondent aux critères. S’il y a plus d’enregistrements, la méthode définit la valeur de la propriété EntityCollection.PagingCookie renvoyée sur la PageInfo.PagingCookie propriété de QueryExpression et envoie une autre demande.

/// <summary>
/// Returns all records matching the criteria
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="query">The QueryExpression query</param>
/// <param name="page">The page size to use. Defaults to 5000</param>
/// <returns>All the records that match the criteria</returns>
static EntityCollection RetrieveAll(IOrganizationService service, 
QueryExpression query,
int page = 5000)
{
    // The records to return
    List<Entity> entities = new();

    // Set the page
    query.PageInfo.PageNumber = 1;
    // Set the count
    query.PageInfo.Count = page;

    while (true)
    {
        // Get the records
        EntityCollection results = service.RetrieveMultiple(query);

        entities.AddRange(results.Entities);

        if (!results.MoreRecords)
        {
            //Stop if there are no more records
            break;
        }
        // Set the PagingCookie with the PagingCookie from the previous query
        query.PageInfo.PagingCookie = results.PagingCookie;

        // Update the PageNumber
        query.PageInfo.PageNumber++;
    }

    return new EntityCollection(entities);
}

Vous pouvez adapter l’exemple Démarrage rapide : exécuter une requête du SDK pour .NET (C#) pour tester les requêtes QueryExpression en procédant comme suit :

  1. Ajoutez la méthode statique RetrieveAll à la classe Program.
  2. Modifiez la méthode Main comme indiqué ci-dessous :
static void Main(string[] args)
{
    using (ServiceClient serviceClient = new(connectionString))
    {
        if (serviceClient.IsReady)
        {
            //WhoAmIResponse response = 
            //    (WhoAmIResponse)serviceClient.Execute(new WhoAmIRequest());

            //Console.WriteLine("User ID is {0}.", response.UserId);

            QueryExpression query = new("contact")
            {
                ColumnSet = new ColumnSet("fullname", "jobtitle", "annualincome"),
                Orders = {
                    { 
                        new OrderExpression(
                            attributeName: "fullname", 
                            orderType: OrderType.Descending) 
                    }
                }
            };

            EntityCollection records = RetrieveAll(service: serviceClient,
                        query: query)

            Console.WriteLine($"Success: {records.Entities.Count}");
        }
        else
        {
            Console.WriteLine(
                "A web service connection was not established.");
        }
    }

    // Pause the console so it does not close.
    Console.WriteLine("Press the <Enter> key to exit.");
    Console.ReadLine();
}

Important

Cette requête renverra TOUS les enregistrements correspondant aux critères. Assurez-vous d’inclure des éléments de filtre pour limiter les résultats.

Tri et pagination

La façon dont une page est triée fait une grande différence lors de la pagination des données. Si les informations de tri des résultats sont ambiguës, Dataverse ne peut pas renvoyer de manière cohérente ou efficace les données paginées.

Spécifiez un ordre pour votre requête. Avec FetchXml, si vous n’ajoutez aucun élément de commande à votre requête, Dataverse ajoute une commande basée sur la clé primaire de la table. Cependant QueryExpression ne le fait pas, et lorsque votre requête spécifie distinct des résultats, aucune valeur de clé primaire n’est renvoyée, donc Dataverse peut pas ajouter cet ordre par défaut. Vous devez spécifier un ordre de pagination. Sans aucun ordre spécifié, les résultats de la requête distinct peuvent être renvoyés dans un ordre aléatoire. OData ne propose aucune option pour renvoyer des résultats distincts, mais vous devez toujours appliquer un ordre lors de la récupération des résultats paginés.

La pagination est dynamique. Chaque requête est évaluée de manière indépendante au fur et à mesure qu’elle est reçue. Un cookie de pagination indique à Dataverse la page précédente. Avec ces données de cookie de pagination, Dataverse peut commencer par l’enregistrement suivant après le dernier de la page précédente.

La pagination fonctionnera mieux à l’avenir. Si vous revenez en arrière et récupérez une page que vous avez précédemment récupérée, les résultats peuvent être différents car des enregistrements peuvent être ajoutés, supprimés ou modifiés depuis la dernière récupération de la page. En d’autres termes, si la taille de votre page est de 50 et que vous revenez en arrière, vous obtenez 50 enregistrements, mais ce ne sont peut-être pas les mêmes 50 enregistrements. Si vous continuez à avancer dans les pages d’un jeu de données, vous pouvez vous attendre à ce que tous les enregistrements soient renvoyés dans un ordre cohérent.

Le tri déterministe est important

Le tri déterministe signifie qu’il existe un moyen de calculer un ordre de manière cohérente. Avec un ensemble d’enregistrements donné, les enregistrements sont toujours renvoyés dans le même ordre. Si vous avez besoin d’ordres et de pagination cohérents, vous devez inclure des valeurs uniques ou une combinaison de valeurs de colonne et spécifier un ordre pour qu’elles soient évaluées.

Exemple non déterministe

Examinons un exemple qui est non déterministe. Ce jeu de données contient uniquement des informations sur l’État et le Statut et est filtré pour renvoyer uniquement les enregistrements dans un État ouvert. Les résultats sont classés par Statut. Les trois premières pages sont demandées. Les résultats ressemblent à ce qui suit :

État Statut Page
Ouvert Actif 1. Début
Ouvert Actif 1
Ouvert Actif 1 Fin
Ouvert Actif
Ouvert Actif
Ouvert Inactif
Ouvert Inactif

Le cookie de pagination enregistre les informations sur le dernier enregistrement de la page. Lorsque la page suivante est demandée, le dernier enregistrement de la première page n’est pas inclus. Cependant, compte tenu des données non déterministes, rien ne garantit que les deux autres enregistrements de la première page ne soient pas inclus dans la deuxième page.

Pour obtenir un tri déterministe, ajoutez des ordres aux colonnes contenant des valeurs uniques ou des valeurs semi-uniques.

Exemple déterministe

Cette requête est similaire à la requête non déterministe, mais elle inclut la colonne ID de cas qui inclut des valeurs uniques. Il est également trié par Statut, mais également par ID de cas. Les résultats ressemblent à ce qui suit :

État Statut ID d’incident Page
Ouvert Actif Incident-0010 1. Début
Ouvert Actif Incident-0021 1
Ouvert Actif Incident-0032 1 Fin
Ouvert Actif Incident-0034
Ouvert Actif Incident-0070
Ouvert Inactif Incident-0015
Ouvert Inactif Incident-0047

Dans la page suivante, le cookie aura Case-0032 stocké comme dernier enregistrement de la première page ; par conséquent, la page deux commencera avec l’enregistrement suivant après cet enregistrement. Les résultats ressemblent à ce qui suit :

État Statut ID d’incident Page
Ouvert Actif Incident-0010 1. Début
Ouvert Actif Incident-0021 1
Ouvert Actif Incident-0032 1 Fin
Ouvert Actif Incident-0034 2. Début
Ouvert Actif Incident-0070 2
Ouvert Inactif Incident-0015 2 Fin
Ouvert Inactif Incident-0047

Étant donné que cette requête tri les valeurs de colonne uniques, l’ordre est cohérent.

Pratiques recommandées pour les tris lors de la pagination des données

Notes

Lorsque cela est possible, les requêtes doivent être triées en fonction de la clé primaire de la table, car Dataverse est optimisé par défaut pour le tri sur la clé primaire. Le tri en fonction de champs non uniques ou complexes entraîne une surcharge excessive et des requêtes plus lentes.

Lorsque vous récupérez un ensemble limité de données à afficher dans une application, ou si vous devez renvoyer plus de 5 000 lignes de données, vous devez paginer les résultats. Les choix effectués pour déterminer l’ordre des résultats peuvent déterminer si les lignes de chaque page de données que vous récupérez chevauchent d’autres pages. Sans un tri approprié, le même enregistrement peut apparaître sur plusieurs pages.

Pour éviter que le même enregistrement apparaisse sur plusieurs pages, appliquez les pratiques recommandées suivantes :

Il est préférable d’inclure une colonne possédant un identificateur unique. Par exemple :

  • Colonnes de clé primaire de la table
  • Colonnes de numérotation automatique
  • ID utilisateur/contact

Si vous ne pouvez pas inclure une colonne avec un identificateur unique, incluez plusieurs champs qui généreront très probablement des combinaisons uniques. Par exemple :

  • Prénom + nom + adresse e-mail
  • Nom complet + adresse e-mail
  • Adresse e-mail + nom de l’entreprise

Anti-modèles pour les tris lors de la pagination des données

Les choix de tri suivants doivent être évités :

  • Les tris qui n’incluent pas d’identificateurs uniques

  • Les tris sur des champs calculés

  • Tris avec un ou plusieurs champs qui ne fournissent probablement pas un caractère unique, tels que :

    • Statut et état
    • Choix ou Oui/Non
    • Nommez les valeurs par elles-mêmes. Par exemple name, firstname, lastname
    • Champs de texte comme les titres, les descriptions et le texte sur plusieurs lignes
    • Champs de nombres non uniques

Étapes suivantes

Découvrez comment agréger des données.

Notes

Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)

Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).