Search code examples
sharepointmicrosoft-graph-apimicrosoft-graph-sdks

How to delete multiple drive items in a batch using GraphAPI SDK


I want to delete a few dozen or so items in a SharePoint document library using the Graph API SDK. I can delete them individually like this:

for (var item in driveItems) {
    await clientCtx
        .Sites[site.Id]
        .Drives[drive.Id]
        .Items[item.Id]
        .Request()
        .DeleteAsync();
}

but as the number of items may grow, this becomes slow. Is there anyway to delete multiple items in one blast/batch?

I'm constrained to use the Graph API SDK and C# -- I'm not allowed to form HTTP/JSON queries manually.


Solution

  • You will have to use batch request. The Graph .NET SDK v5 has the BatchRequestContentCollection which represents a collection of all batch requests. Inside each batch request you can have 20 requests.

    static async Task RemoveFiles(GraphServiceClient client, string driveId, List<string> fileIds)
    {
        var batchCollection = new BatchRequestContentCollection(client);
        for (int i = 0; i < fileIds.Count; i += 20)
        {
            var selectedFileIds = fileIds.Skip(i).Take(20);
            foreach (var fileId in selectedFileIds)
            {
                // to delete the file permanently, use the following request instead
                var request = client.Drives[driveId].Items[fileId].PermanentDelete.ToPostRequestInformation();
                // to move the file to the recycle bin, use the following request instead
                // var request = client.Drives[driveId].Items[fileId].ToDeleteRequestInformation();
                await batchCollection.AddBatchRequestStepAsync(request, fileId);
            }
        }
        var batchResponse = await client.Batch.PostAsync(batchCollection);
        var responsesStatusCodes = await batchResponse.GetResponsesStatusCodesAsync();
        foreach (var response in responsesStatusCodes)
        {
            Console.WriteLine($"Response for drive item {response.Key} with status code {response.Value}");
            if (response.Value != System.Net.HttpStatusCode.NoContent)
            {
                try
                {
                    var responseMessage = await batchResponse.GetResponseByIdAsync(response.Key);
                    var stringContent = await responseMessage.Content.ReadAsStringAsync();
                    var odataError = await KiotaJsonSerializer.DeserializeAsync<ODataError>(stringContent);
                    Console.WriteLine($"Error: {odataError.Message}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error: {ex.Message}");
                }
            }
        }
    }
    

    If all items in some folder should be deleted, it would be better to delete the whole folder instead of each file one by one.