You could take advantage of feature called Request Batching, which in turn could dramatically affect the performance by minimizing the number of messages that are passed between the client and the server.
From the documentation:
The CSOM programming model is built around request batching. When you
work with the CSOM, you can perform a series of data operations on the
ClientContext object. These operations are submitted to the server in
a single request when you call the ClientContext.BeginExecuteQuery
method.
For comparison lets demonstrate two ways the updating of multiple list items:
Standard way:
foreach (var item in items)
{
item["LastReviewed"] = DateTime.Now;
item.Update();
ctx.ExecuteQuery();
}
Batched update:
foreach (var item in items)
{
item["LastReviewed"] = DateTime.Now;
item.Update();
}
ctx.ExecuteQuery();
Note: in the second approach only a single batched request is
submitted to the server
Complete example
var listTitle = "Documents";
var folderUrl = "Archive/2013";
using (var ctx = GetContext(url, userName, password))
{
//1. Get list items operation
var list = ctx.Web.Lists.GetByTitle(listTitle);
var items = list.GetListItems(folderUrl);
ctx.Load(items);
ctx.ExecuteQuery();
//2. Update list items operation
var watch = Stopwatch.StartNew();
foreach (var item in items)
{
if(Convert.ToInt32(item["FSObjType"]) == 1) //skip folders
continue;
item["LastReviewed"] = DateTime.Now;
item.Update();
//ctx.ExecuteQuery();
Console.WriteLine("{0} has been updated", item["FileRef"]);
}
ctx.ExecuteQuery(); //execute batched request
watch.Stop();
Console.WriteLine("Update operation completed: {0}", watch.ElapsedMilliseconds);
Console.ReadLine();
}
where GetListItems
is the extension method for getting list items located under a specific folder:
using System.Linq;
using Microsoft.SharePoint.Client;
namespace SharePoint.Client.Extensions
{
public static class ListCollectionExtensions
{
/// <summary>
/// Get list items located under specific folder
/// </summary>
/// <param name="list"></param>
/// <param name="relativeFolderUrl"></param>
/// <returns></returns>
public static ListItemCollection GetListItems(this List list, string relativeFolderUrl)
{
var ctx = list.Context;
if (!list.IsPropertyAvailable("RootFolder"))
{
ctx.Load(list.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
}
var folderUrl = list.RootFolder.ServerRelativeUrl + "/" + relativeFolderUrl;
var qry = CamlQuery.CreateAllItemsQuery();
qry.FolderServerRelativeUrl = folderUrl;
var items = list.GetItems(qry);
return items;
}
}
}