Freigeben über


Verwenden der Microsoft Graph SDKs zum Batchen von Anforderungen

Batchverarbeitung ist eine Möglichkeit, mehrere Anforderungen in einer einzelnen HTTP-Anforderung zu kombinieren. Die Anforderungen werden in einer einzelnen JSON-Nutzlast kombiniert, die über POST an den \$batch Endpunkt gesendet wird. Microsoft Graph SDKs verfügen über eine Reihe von Klassen, um die Erstellung von Batchnutzlasten und das Analysieren von Batchantwortnutzlasten zu vereinfachen.

Wichtig

Aktuelle Einschränkungen bei der JSON-Batchverarbeitung in Microsoft Graph finden Sie unter Bekannte Probleme.

Erstellen einer Batchanforderung

Die Microsoft Graph SDKs bieten drei Klassen für die Arbeit mit Batchanforderungen und -antworten.

  • BatchRequestStep : Stellt eine einzelne Anforderung (z GET /me. B. ) innerhalb eines Batches dar. Es ermöglicht das Zuweisen eines eindeutigen Bezeichners zur Anforderung und das Angeben von Abhängigkeiten zwischen Anforderungen.
  • BatchRequestContent : Vereinfacht das Erstellen der Batchanforderungsnutzlast. Sie enthält mehrere BatchRequestStep-Objekte .
  • BatchResponseContent : Vereinfacht die Analyse der Antwort aus einer Batchanforderung. Es ermöglicht Ihnen, alle Antworten abzurufen, eine bestimmte Antwort nach ID abzurufen und die @odata.nextLink Eigenschaft abzurufen, falls vorhanden.

Automatische Batchverarbeitung für Anforderungsgrenzwerte

Das Microsoft Graph SDK verarbeitet automatisch Batchverarbeitungsanforderungen in Bezug auf den Grenzwert von 20 Anforderungen pro Batch. Dies bedeutet, dass das SDK die Anforderungen im Hintergrund in separate Batches aufteilt, wenn Ihr Code diesen Grenzwert überschreitet. Dadurch wird sichergestellt, dass jeder Batch die Einschränkung erfüllt. Sie müssen keine Logik mehr manuell implementieren, um dieses Batchverarbeitungslimit zu behandeln, wodurch Ihr Code übersichtlicher und einfacher zu verwalten ist.

Einfaches Batchverarbeitungsbeispiel

In diesem Beispiel wird gezeigt, wie mehrere Anforderungen in einem Batch gesendet werden, die nicht voneinander abhängig sind. Der Dienst kann die Anforderungen in beliebiger Reihenfolge ausführen. In diesem Beispiel wird der Benutzer und die Kalenderansicht des Benutzers für den aktuellen Tag abgerufen.

// 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}");
}

Batches mit abhängigen Anforderungen

In diesem Beispiel wird gezeigt, wie mehrere Anforderungen in einem Batch gesendet werden, die voneinander abhängig sind. Der Dienst führt die Anforderung in der von den Abhängigkeiten angegebenen Reihenfolge aus. In diesem Beispiel wird dem Kalender des Benutzers ein Ereignis mit einer Startzeit während des aktuellen Tages hinzugefügt und die Kalenderansicht des Benutzers für den aktuellen Tag abgerufen. Um sicherzustellen, dass die zurückgegebene Kalenderüberprüfung das neu erstellte Ereignis enthält, wird die Anforderung für die Kalenderansicht als abhängig von der Anforderung zum Hinzufügen des neuen Ereignisses konfiguriert. Dadurch wird sichergestellt, dass die Ereignisanforderung zum Hinzufügen zuerst ausgeführt wird.

Hinweis

Wenn bei der Anforderung zum Hinzufügen von Ereignissen ein Fehler auftritt, schlägt die Anforderung zum Abrufen der Kalenderansicht mit einem 424 Failed Dependency Fehler fehl.

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}");
}