c# - 我应该使用一个或多个 ClientContext 来更新一个非常大的列表吗?
问题描述
我需要更新一个大型 SharePoint 列表,大约 10,000 项或更多。每个 ListItem 有 4 列要更新。我不知道这种情况下最好的方法是什么:
- 使用 1 个 ClientContext,以 n 行的批次获取 ListItemCollection,遍历每个 ListItem 并在下一批之前更新其列。或者
- 以 n 行的批次获取 ListItemCollectionPosition 列表,遍历每个 ListItemCollectionPosition,创建新的 ClientContext,获取 ListItemCollection 然后更新。
方法一
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);
}
方法二
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 和 2 中,我将 ViewFields 设置为限制传输的数据量。
在方法 2UpdateItem
中,方法在positions
收集满后执行。为什么positions
在填充集合时不更新列表项 - 您可以使用 yield 属性实现枚举器。
public static IEnumerable<ListItemCollectionPosition> GetPositions()
{
do
{
...
yield return pos;
...
} while (pos != null);
}
推荐阅读
- r - 如何访问使用输入传递的传单地图?
- azure - 如何在 SPA Nuxt Web 应用程序的客户端访问 Azure 应用程序设置
- java - 在 MongoDB 中更新值加 1
- r-markdown - 在 RMarkdown 中编织时服务器意外关闭连接
- microsoft-graph-api - js Office插件试图获取文本输入字段以将变量传递给图形API调用
- python - 将 4 个十六进制字节转换为 RGBA 颜色
- python - 使用 seaborn 联合图返回 hexbin 中的值数组
- linux - 在 Dante Socks5 Server ubuntu 中允许绑定连接
- python - 无法在 python 中读取地理空间数据(img、rrd、ige 文件)
- python - Python:更改 JSON 中的元素