1

I need to update a large SharePoint List, about 10,000 items or more. Each ListItem has 4 columns to be updated. I don't know what the best approach for this scenario is:

  1. Use 1 ClientContext, fetch ListItemCollection in batch of n rows, loop through each ListItem and update its columns before the next batch. Or
  2. Fetch a list of ListItemCollectionPosition in batch of n rows, loop through each ListItemCollectionPosition, create a new ClientContext, fetch ListItemCollection and then update.

Method 1

using (ClientContext ctx = new ClientContext(url))
{
   ctx.Credentials = new SharePointOnlineCredentials(username,password);
   List list = ctx.Web.Lists.GetByTitle("mylist");
   ctx.Load(list);
   ctx.ExecuteQuery();
   ListItemCollectionPosition pos = null;
   CamlQuery camlQuery = new CamlQuery
   {
       ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
   };
   do           
   {
        if (pos != null)
        {
            camlQuery.ListItemCollectionPosition = pos;
        }
        ListItemCollection listItemCollection = list.GetItems(camlQuery);
        ctx.Load(listItemCollection);
        ctx.ExecuteQuery();
        pos = listItemCollection.ListItemCollectionPosition;
        foreach(ListItem item in listItemCollection)
        {
            item["col1"] = "abc";
            item["col2"] = "def";
            item["col3"] = "ghi";
            item["col4"] = "jkl";
            item.Update();
        }
        ctx.ExecuteQuery();
    } while (pos != null);
}

Method 2

private void UpdateList()
{
   using (ClientContext ctx = new ClientContext(url))
   {
       ctx.Credentials = new SharePointOnlineCredentials(username,password);
       List list = ctx.Web.Lists.GetByTitle("mylist");
       ctx.Load(list);
       ctx.ExecuteQuery();
       ListItemCollectionPosition pos = null;
       CamlQuery camlQuery = new CamlQuery
       {
           ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
       };
       List<ListItemCollectionPosition> positions = new List<ListItemCollectionPosition>();
       do           
       {
           if (pos != null)
           {
               camlQuery.ListItemCollectionPosition = pos;
           }
           ListItemCollection listItemCollection = list.GetItems(camlQuery);
           ctx.Load(listItemCollection);
           ctx.ExecuteQuery();
           pos = listItemCollection.ListItemCollectionPosition;
           positions.Add(pos);            
       } while (pos != null);
       List<Task> tasks = new List<Task>();
       foreach(var position in positions)
       {
           tasks.Add(UpdateItem(position));
       }
       Task.WaitAll(tasks.ToArray());
    }
}
private Task UpdateItem(ListItemCollectionPosition pos)
{
   using (ClientContext ctx = new ClientContext(url))
   {
      ctx.Credentials = new SharePointOnlineCredentials(username,password);
      List list = ctx.Web.Lists.GetByTitle("mylist");
      ctx.Load(list);
      ctx.ExecuteQuery();
      CamlQuery camlQuery = new CamlQuery
      {
          ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
      };
      camlQuery.ListItemCollectionPosition = pos;
      ListItemCollection listItemCollection = list.GetItems(camlQuery);
      ctx.Load(listItemCollection);
      ctx.ExecuteQuery();
      foreach(ListItem item in listItemCollection)
      {
           item["col1"] = "abc";
           item["col2"] = "def";
           item["col3"] = "ghi";
           item["col4"] = "jkl";
           item.Update();
      }
      return ctx.ExecuteQueryAsync();
    }
}

1 Answer 1

0

Technically, either will work, although option 2 will take a lot longer. Using a single client context will work just fine.

Watch out for throttling. Read this, especially the part about incremental retry.

3
  • If the List has thousands or hundred thousands of ListItems, is it safe to keep a single ClientContext open for that long?
    – Jack Le
    Mar 16, 2019 at 3:07
  • It's always worked for me, but "your mileage may vary". Is it safe to generate thousands of client contexts? Nothing is guaranteed and large scale automated jobs can and will have issues come up - you need to plan to mitigate those. Best bet - if you have doubts, try both approaches against a test site (you should be doing this anyway) Mar 16, 2019 at 6:16
  • Strangely enough, both methods take about the same amount of time for 1000 records on my test site. I'm just worried that method 1 will keep the connection open for too long. Method 2 will dispose all context when it finishes updating each batch (around 100 ListItem)
    – Jack Le
    Mar 16, 2019 at 9:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.