Paginer des résultats à l’aide de FetchXml
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
- N’utilisez pas l’attribut
top
de l’élément fetch avec la pagination. Ces différentes méthodes de limitation des résultats d’une requête ne sont pas compatibles. - Le tri joue un rôle important dans l’obtention de résultats de pagination cohérents. En savoir plus sur le tri et la pagination
Modèles de pagination
Dataverse a deux modèles de pagination : simple et avec des cookies de pagination :
Simple
- Utilise uniquement les attributs
count
etpage
de l’élément fetch - 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
- Utilise les attributs
count
,page
etpaging-cookie
de l’élément fetch - Définit la valeur de l’attribut
paging-cookie
sur la valeur renvoyée avec la page précédente - Recommandé pour toutes les tailles du jeu de données
- Certaines requêtes n’autorisent pas les cookies de pagination
- En savoir plus sur l’utilisation de cookies de pagination
Pagination simple
Vous pouvez demander la première page en définissant l’attribut page
de l’élément fetch sur 1 et l’attribut count
sur la taille de la page avant d’envoyer la requête :
<fetch count='3' page='1'>
<entity name='account'>
<attribute name='name' />
<order attribute='name' />
<order attribute='accountid' />
</entity>
</fetch>
Pour obtenir les trois enregistrements suivants, incrémentez la valeur page
et envoyez une autre requête.
<fetch count='3' page='2'>
<entity name='account'>
<attribute name='name' />
<order attribute='name' />
<order attribute='accountid' />
</entity>
</fetch>
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. Le nombre total de lignes qui peuvent être récupérées à l’aide d’une simple pagination est de 50 000. 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 dans les résultats et aide Dataverse à récupérer la ligne de données suivante le plus rapidement possible et doit être utilisé lorsqu’il est fourni. Vous ne devez pas modifier les données du cookie de pagination, définissez simplement la valeur sur l’attribut paging-cookie
de l’élément fetch et incrémentez la valeur de l’attribut page
pour les requêtes 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’un attribut link-entity
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.
Exemples de cookies de pagination
La manière d’utiliser les cookies de pagination dépend si vous utilisez le SDK pour .NET ou l’API Web.
La méthode statique RetrieveAll
suivante renverra tous les enregistrements correspondant à la requête FetchXml, 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 d’autres enregistrements, la méthode définit la valeur de la propriété EntityCollection.PagingCookie renvoyée sur l’attribut paging-cookie
de l’élément fetch et envoie une autre requête.
/// <summary>
/// Returns all records matching the criteria
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="fetchXml">The fetchXml Query string</param>
/// <param name="pageSize">The page size to use. Default is 5000</param>
/// <returns>All the records that match the criteria</returns>
static EntityCollection RetrieveAll(IOrganizationService service, string fetchXml, int pageSize = 5000)
{
// The records to return
List<Entity> entities = new();
XElement fetchNode = XElement.Parse(fetchXml);
int page = 1; //Start with page 1
//Set the page
fetchNode.SetAttributeValue("page", page);
// Set the page size
fetchNode.SetAttributeValue("count", pageSize);
while (true)
{
// Get the page
EntityCollection results = service.RetrieveMultiple(new FetchExpression(fetchNode.ToString()));
entities.AddRange(results.Entities);
if (!results.MoreRecords)
{
break;
}
// Set the fetch paging-cookie attribute with the paging cookie from the previous query
fetchNode.SetAttributeValue("paging-cookie", results.PagingCookie);
fetchNode.SetAttributeValue("page", page++);
}
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 FetchXml en procédant comme suit :
- Ajoutez la méthode statique
RetrieveAll
à la classeProgram
. - 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);
string fetchQuery = @"<fetch count='3' page='1'>
<entity name='contact'>
<attribute name='fullname'/>
<attribute name='jobtitle'/>
<attribute name='annualincome'/>
<order descending='true' attribute='fullname'/>
</entity>
</fetch>";
EntityCollection records = RetrieveAll(service: serviceClient,
fetchXml: fetchQuery,
pageSize: 25);
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.
Ordering and paging
How a page is ordered makes a big difference when paging data. If the information about how the results are ordered is ambiguous, Dataverse can't consistently or efficiently return paged data.
Specify an order for your query. With FetchXml, if you don't add any order elements to your query, Dataverse adds an order based on the primary key of the table. However QueryExpression does not, and when your query specifies distinct
results, no primary key values are returned, so Dataverse can't add this default order. You must specify a paging order. Without any order specified, distinct
query results might be returned in random order. OData doesn't provide any option to return distinct results, but you should still apply an order when retrieving paged results.
Paging is dynamic. Each request is evaluated independently as they're received. A paging cookie tells Dataverse the previous page. With this paging cookie data, Dataverse can start with the next record after the last one on the preceding page.
Paging works best going forward. If you go back and retrieve a page you previously retrieved, the results can be different because records could be added, deleted, or modified during since you last retrieved the page. In other words, if your page size is 50 and you go back, you get 50 records, but they might not be the same 50 records. If you keep progressing forward through the pages of a data set, you can expect all the records are returned in a consistent sequence.
Deterministic ordering is important
Deterministic ordering means that there's a way to calculate an order consistently. With a given set of records, the records are always returned in the same order. If you need consistent orders and paging, you must include some unique values or combination of column values that are and specify an order for them to be evaluated.
Nondeterministic example
Let's look at an example that is nondeterministic. This data set contains only State and Status information and is filtered to only return records in an open State. The results are ordered by Status. The first three pages are requested. The results look like this:
State | Status | Page |
---|---|---|
Open | Active | 1 Start |
Open | Active | 1 |
Open | Active | 1 End |
Open | Active | |
Open | Active | |
Open | Inactive | |
Open | Inactive |
The paging cookie saves information about the last record on the page. When the next page is requested, the last record from the first page isn't included. However, given the nondeterministic data, there's no guarantee that the other two records on the first page aren't included in the second page.
To achieve deterministic ordering, add orders on columns that contain unique values, or values that are semi-unique.
Deterministic example
This query is like the nondeterministic one, but it includes the Case ID column that includes unique values. It's also ordered by Status, but also ordered using Case ID. The results look like this:
State | Status | Case ID | Page |
---|---|---|---|
Open | Active | Case-0010 | 1 Start |
Open | Active | Case-0021 | 1 |
Open | Active | Case-0032 | 1 End |
Open | Active | Case-0034 | |
Open | Active | Case-0070 | |
Open | Inactive | Case-0015 | |
Open | Inactive | Case-0047 |
In the next page, the cookie will have Case-0032
stored as the last record in the first page, so page two will start with the next record after that record. The results look like this:
State | Status | Case ID | Page |
---|---|---|---|
Open | Active | Case-0010 | 1 Start |
Open | Active | Case-0021 | 1 |
Open | Active | Case-0032 | 1 End |
Open | Active | Case-0034 | 2 Start |
Open | Active | Case-0070 | 2 |
Open | Inactive | Case-0015 | 2 End |
Open | Inactive | Case-0047 |
Because this query orders unique column values, the order is consistent.
Best practices for orders when paging data
Notes
When possible, queries should order on the primary key for the table because Dataverse is optimized for ordering on the primary key by default. Ordering by non-unique or complex fields cause excess overhead and slower queries.
When you retrieve a limited set of data to display in an application, or if you need to return more than 5,000 rows of data, you need to page the results. The choices you make in determining the order of the results can determine whether the rows in each page of data you retrieve overlaps with other pages. Without proper ordering, the same record can appear in more than one page.
To prevent the same record from appearing in more than one page, apply the following best practices:
It's best to include a column that has a unique identifier. For example:
- Table primary key columns
- Autonumber columns
- User/contact IDs
If you can't include a column with a unique identifier, include multiple fields that will most likely result in unique combinations. For example:
- First name + last name + email address
- Full name + email address
- Email address + company name
Anti-patterns for orders when paging data
The following are ordering choices to avoid:
Orders that don't include unique identifiers
Orders on calculated fields
Orders that have single or multiple fields that aren't likely to provide uniqueness such as:
- Status and state
- Choices or Yes/No
- Name values by themselves. For example
name
,firstname
,lastname
- Text fields like titles, descriptions, and multi-line text
- Non unique number fields
É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é).
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : pendant toute l’année 2024, nous allons éliminer progressivement Problèmes GitHub comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, voir :Soumettre et afficher des commentaires pour