您好, 我的客户端有一个Sharepoint Server 2013 on Premise。他想在多个文件上编写元数据。更具体地说,他想要选择一个文件夹,然后应用程序应该为该文件夹中的每个文件/文件夹的列中写入相同的值。
我写了一个CAML查询,它返回所选文件夹下面的所有文件/文件夹。然后我写下每个项目的值并更新它。
我想编写一个应用程序,我的客户端可以选择一个文件夹。之后,软件应该更新该文件夹下的所有文件。 我想用C#和CSOM编写这个应用程序。
这很慢。每个文件夹有数千个文件,只需要几个小时就可以完成一个文件夹。
有没有办法加快速度?
CAML-Query是否也可以更新值?
做我想做的事情的推荐方法是什么?
是否有其他方法可以实现客户的需求?
感谢您的帮助。
答案 0 :(得分:2)
您可以利用名为Request Batching的功能,这可以通过最大限度地减少客户端和服务器之间传递的消息数
来显着影响性能。CSOM编程模型是围绕请求批处理构建的。当你 使用CSOM,您可以执行一系列数据操作 ClientContext对象。这些操作将提交给服务器 致电
ClientContext.BeginExecuteQuery
时的一个请求 方法
为了进行比较,我们演示了两种更新多个列表项的方法:
标准方式:
foreach (var item in items)
{
item["LastReviewed"] = DateTime.Now;
item.Update();
ctx.ExecuteQuery();
}
批量更新:
foreach (var item in items)
{
item["LastReviewed"] = DateTime.Now;
item.Update();
}
ctx.ExecuteQuery();
注意:在第二种方法中,只有一个批处理请求 提交到服务器
完整示例
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();
}
其中GetListItems
是获取位于特定文件夹下的列表项的扩展方法:
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;
}
}
}