Utiliser les Kits de développement logiciel (SDK) Microsoft Graph pour traiter les demandes par lot

Le traitement par lot est un moyen de combiner plusieurs requêtes en une seule requête HTTP. Les requêtes sont combinées dans une seule charge utile JSON, qui est envoyée via POST au point de \$batch terminaison. Les kits SDK Microsoft Graph disposent d’un ensemble de classes pour simplifier la création de charges utiles par lots et l’analyse des charges utiles de réponse par lot.

Importante

Pour connaître les limitations actuelles du traitement par lots JSON dans Microsoft Graph, consultez Problèmes connus.

Créer une demande de lot

Les Kits de développement logiciel (SDK) Microsoft Graph fournissent trois classes pour fonctionner avec les requêtes et réponses par lots.

  • BatchRequestStep : représente une seule requête (telle que GET /me) dans un lot. Il permet d’attribuer un identificateur unique à la requête et de spécifier les dépendances entre les requêtes.
  • BatchRequestContent : simplifie la création de la charge utile de la demande de lot. Il contient plusieurs objets BatchRequestStep .
  • BatchResponseContent : simplifie l’analyse de la réponse à partir d’une demande de lot. Il vous permet d’obtenir toutes les réponses, d’obtenir une réponse spécifique par ID et d’obtenir la propriété si @odata.nextLink elle est présente.

Traitement par lot automatique pour les limites de requêtes

Le Kit de développement logiciel (SDK) Microsoft Graph gère automatiquement les demandes de traitement par lot en fonction de la limite de 20 demandes par lot. Cela signifie que si votre code dépasse cette limite, le Kit de développement logiciel (SDK) fractionne les requêtes en lots distincts en arrière-plan. Cela garantit que chaque lot est conforme à la limitation. Vous n’avez plus besoin d’implémenter manuellement la logique pour gérer cette limite de traitement par lots, ce qui rend votre code plus propre et plus facile à gérer.

Exemple de traitement par lot simple

Cet exemple montre comment envoyer plusieurs demandes dans un lot qui ne dépendent pas les unes des autres. Le service peut exécuter les requêtes dans n’importe quel ordre. Cet exemple obtient l’utilisateur et obtient l’affichage calendrier de l’utilisateur pour le jour actuel.

// Use the request builder to generate a regular
// request to /me
var userRequest = graphClient.Me.ToGetRequestInformation();

var today = DateTime.Now.Date;

// Use the request builder to generate a regular
// request to /me/calendarview?startDateTime="start"&endDateTime="end"
var eventsRequest = graphClient.Me.CalendarView
    .ToGetRequestInformation(requestConfiguration =>
        {
            requestConfiguration.QueryParameters.StartDateTime =
                today.ToString("yyyy-MM-ddTHH:mm:ssK");
            requestConfiguration.QueryParameters.EndDateTime =
                today.AddDays(1).ToString("yyyy-MM-ddTHH:mm:ssK");
        });

// Build the batch
var batchRequestContent = new BatchRequestContentCollection(graphClient);

// Using AddBatchRequestStepAsync adds each request as a step
// with no specified order of execution
var userRequestId = await batchRequestContent
    .AddBatchRequestStepAsync(userRequest);
var eventsRequestId = await batchRequestContent
    .AddBatchRequestStepAsync(eventsRequest);

var returnedResponse = await graphClient.Batch.PostAsync(batchRequestContent);

// De-serialize response based on known return type
try
{
    var user = await returnedResponse
        .GetResponseByIdAsync<User>(userRequestId);
    Console.WriteLine($"Hello {user.DisplayName}!");
}
catch (Exception ex)
{
    Console.WriteLine($"Get user failed: {ex.Message}");
}

// For collections, must use the *CollectionResponse class to deserialize
// The .Value property will contain the *CollectionPage type that the Graph client
// returns from GetAsync().
try
{
    var events = await returnedResponse
        .GetResponseByIdAsync<EventCollectionResponse>(eventsRequestId);
    Console.WriteLine(
        $"You have {events.Value?.Count} events on your calendar today.");
}
catch (Exception ex)
{
    Console.WriteLine($"Get calendar view failed: {ex.Message}");
}

Lots avec des demandes dépendantes

Cet exemple montre comment envoyer plusieurs demandes dans un lot qui dépendent les unes des autres. Le service exécute la requête dans l’ordre spécifié par les dépendances. Cet exemple ajoute un événement avec une heure de début du jour en cours au calendrier de l’utilisateur et obtient l’affichage calendrier de l’utilisateur pour le jour actuel. Pour vous assurer que la révision du calendrier retournée inclut le nouvel événement créé, la demande pour l’affichage Calendrier est configurée comme dépendant de la demande d’ajout du nouvel événement. Cela garantit que la demande d’ajout d’événement s’exécute en premier.

Remarque

Si la demande d’ajout d’événement échoue, la demande d’affichage d’obtention du calendrier échoue avec une 424 Failed Dependency erreur.

var today = DateTime.Now.Date;

var newEvent = new Event
{
    Subject = "File end-of-day report",
    Start = new DateTimeTimeZone
    {
        // 5:00 PM
        DateTime = today.AddHours(17)
            .ToString("yyyy-MM-ddTHH:mm:ss"),
        TimeZone = TimeZoneInfo.Local.StandardName,
    },
    End = new DateTimeTimeZone
    {
        // 5:30 PM
        DateTime = today.AddHours(17).AddMinutes(30)
            .ToString("yyyy-MM-ddTHH:mm:ss"),
        TimeZone = TimeZoneInfo.Local.StandardName,
    },
};

// Use the request builder to generate a regular
// POST request to /me/events
var addEventRequest = graphClient.Me.Events
    .ToPostRequestInformation(newEvent);

// Use the request builder to generate a regular
// request to /me/calendarview?startDateTime="start"&endDateTime="end"
var calendarViewRequest = graphClient.Me.CalendarView.ToGetRequestInformation(
    requestConfiguration =>
    {
        requestConfiguration.QueryParameters.StartDateTime =
            today.ToString("yyyy-MM-ddTHH:mm:ssK");
        requestConfiguration.QueryParameters.EndDateTime =
            today.AddDays(1).ToString("yyyy-MM-ddTHH:mm:ssK");
    });

// Build the batch
var batchRequestContent = new BatchRequestContentCollection(graphClient);

// Force the requests to execute in order, so that the request for
// today's events will include the new event created.

// First request, no dependency
var addEventRequestId = await batchRequestContent
    .AddBatchRequestStepAsync(addEventRequest);

// Second request, depends on addEventRequestId
var eventsRequestId = Guid.NewGuid().ToString();
var eventsRequestMessage = await graphClient.RequestAdapter
    .ConvertToNativeRequestAsync<HttpRequestMessage>(calendarViewRequest);
batchRequestContent.AddBatchRequestStep(new BatchRequestStep(
    eventsRequestId,
    eventsRequestMessage,
    [addEventRequestId]));

var returnedResponse = await graphClient.Batch.PostAsync(batchRequestContent);

// De-serialize response based on known return type
try
{
    var createdEvent = await returnedResponse
        .GetResponseByIdAsync<Event>(addEventRequestId);
    Console.WriteLine($"New event created with ID: {createdEvent.Id}");
}
catch (Exception ex)
{
    Console.WriteLine($"Add event failed: {ex.Message}");
}

// For collections, must use the *CollectionResponse class to deserialize
// The .Value property will contain the *CollectionPage type that the Graph client
// returns from GetAsync().
try
{
    var events = await returnedResponse
        .GetResponseByIdAsync<EventCollectionResponse>(eventsRequestId);
    Console.WriteLine(
        $"You have {events.Value?.Count} events on your calendar today.");
}
catch (Exception ex)
{
    Console.WriteLine($"Get calendar view failed: {ex.Message}");
}