我应该使用一个或多个ClientContext更新一个很大的List吗?

时间:2019-03-14 22:50:03

标签: c# sharepoint-online listitem csom

我需要更新大型SharePoint列表,其中约有10,000项或更多。每个ListItem都有4列要更新。我不知道这种情况的最佳方法是:

  1. 使用1个ClientContext,批量获取n行中的ListItemCollection, 遍历每个ListItem并在下一个之前更新其列 批量。或者
  2. 批量获取n行中的ListItemCollectionPosition列表,遍历每个ListItemCollectionPosition,创建一个新的ClientContext,获取ListItemCollection,然后进行更新。

方法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);
}

方法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 个答案:

答案 0 :(得分:1)

在方法1和2中,我将ViewFields设置为限制传输的数据量。

在方法2中,UpdateItem方法在positions集合已满之后执行。为什么在填充positions集合时不更新列表项-您可以实现带有yield属性的枚举器。

public static IEnumerable<ListItemCollectionPosition> GetPositions()
{            
     do           
     {
       ...
       yield return pos;
       ...
     } while (pos != null);
}