批量操作数据的时候,为了提高性能,可以使用ProcessBatchData这个方法,这个方法的参数只有一个,就是一段xml,xml schema的说明参考:点击打开链接。
按照schema的说明,这个xml参数类似于:
<?xml version="1.0" encoding="UTF-8"?>
<ows:Batch>
<Method ID="...">
<SetList>...</SetList>
<SetVar Name="...">...<SetVar>
... ...
</Method>
</ows:Batch>
所以我们需要做的就是构造这样一个xml,把我们想要执行的操作变为这里的Method。
首先定义三个常量,分别是xml的定义,xml的开始和结束标签:
private string XMLTag = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
private string BatchStartTag = "<ows:Batch OnError=\"Continue\">";
private string BatchEndTag = "</ows:Batch>";
其中BatchStartTag使用了一个OnError属性,这个属性有两个值,一个是默认值”Return“,即出错了就停止执行;另一个值是”Continue“,即出错后继续执行下一个Method。
下面的方法是构造一个添加一条item的Method
string BuildNewItemMethod(SPList list)
{
StringBuilder builder = new StringBuilder();
builder.AppendFormat("<Method ID=\"{0}\">
<SetList>{1}</SetList>
<SetVar Name=\"Cmd\">Save</SetVar>
<SetVar Name=\"ID\">{2}</SetVar>", Guid.NewGuid(), list.ID, "New");
builder.Append(BuildSetVarCmd("Title", "Item Title"));
... ...
builder.Append(BuildSetVarCmd("FieldInternalName", "Field value"));
builder.Append("</Method>"); return builder.ToString();
}
string BuildSetVarCmd(string internalName, string value)
{
return string.Format("<SetVar Name=\"urn:schemas-microsoft-com:office:office#{0}\">{1}</SetVar>", internalName, value);
}
每个Method都需要一个唯一的ID,这里使用Guid。Method的第一个子节点是SetList,这里需要指定更新的列表的ID;第二个子节点是SetVar,这个子节点指定命令,创建item和更新item的命令都是”Save“,区别在于第三个子节点SetVar,这个子节点指定了item的ID,如果是创建item这个地方的值是”New“,如果是更新item这个地方的值就是item的ID(item.ID)。这三个子节点是Method必须指定的,然后其他的SetVar节点就可以使用相同的方法构建了,这里用了一个方法”BuildSetVarCmd“来构建。
注意在BuildSetVarCmd中,在每个internalName的前面都加了一个前缀”urn...#“,对于自定义的field,content type和Title,这个前缀是必须的,其他的field不使用这个前缀。
所以以上的方法构建出来的Method类似于:
<Method ID="5E237A33-6EA5-4270-B37D-6CC2F5F44C35">
<SetList>F3BFAF17-1A77-41D9-9435-B96375F76387</SetList>
<SetVar Name="Cmd">Save<SetVar>
<SetVar Name="ID">New</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#Title">Item Title</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#FieldInternalName">Field Value</SetVar>
</Method>
使用同样的方法,用户更新一条item的Method类似于:
<Method ID="<span style="font-family: Arial, Helvetica, sans-serif;">F3BFAF17-1A77-41D9-9435-B96375F76387</span>">
<SetList>5E237A33-6EA5-4270-B37D-6CC2F5F44C35</SetList>
<SetVar Name="Cmd">Save<SetVar>
<SetVar Name="ID">1</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#Title">Item Title</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#FieldInternalName">Field Value</SetVar>
</Method>
删除一条item的Method,只需要指定Cmd为Delete,以及item的ID就行了,类似于
<Method ID="88074250-0642-4B7D-A95F-DAA900F018D2">
<SetList>3A820278-20CC-4802-B670-562BB61AFB8D</SetList>
<SetVar Name="Cmd">Delete<SetVar>
<SetVar Name="ID">1</SetVar>
</Method>
以上就是ProcessBatchData的基本使用方法,以下是需要注意的问题:
1. 不要忘记设置OnError属性,如果希望即使一条Method执行出错,仍然继续执行剩余的Method,需要将OnError设置为Continue。
2. 这个方法默认的返回值是也是xml,例如:
string result = web.ProcessBatchData(cmdXml);
如果执行成功,返回值是:
<Results>
<Result ID="e47356c6-dd36-42c5-8234-eed33b2e0bcd" Code="0">
</Result>
这里的ID就是Method的ID,如果出错了,会返回:
<Results>
<Result ID="e47356c6-dd36-42c5-8234-eed33b2e0bcd" Code="-2130575350">
<ErrorText>Invalid URL Parameter.</ErrorText>
</Result>
</Results>
其中包含了错误号码(Code=”-2130575350“)和具体的错误信息。
3, 对于自定义Field、ContentType或Title 需要使用 urn:schemas-microsoft-com:office:office#加上字段的internal name。否则更新会失败,如果不用internal name会提示找不到field
4. 更新时间类型的值,需要使用SPUtility.CreateISO8601DateTimeFromSystemDateTime()方法将时间转换为标准的格式:
DateTime dt = DateTime.Now;
string value = SPUtility.CreateISO8601DateTimeFromSystemDateTime(dt);
最终生成的xml类似于:
<SetVar Name="urm:schemas-microsoft-com:office:office#Modified">2014-05-22T02:20:05Z</SetVar>
5.ProcessBatchData方法可以更新metadata,参考http://whito-sharepoint.blogspot.hk/2013/11/update-taxonomy-field-process-batch.html
6. ProcessBatchData方法是不能批量上传文档的。
7. 如果列表启用了版本控制,那么执行完ProcessBatchData之后,会自动增加版本。如果不想增加版本,可以先获取item的owshiddenversion这个属性的值保存下来(item[SPBuiltInFieldId.owshiddenversion]),在构建Method的时候,再将这个属性的值赋给item,这样做的效果类似于item.SystemUpdate(false);
<SetVar Name="owshiddenversion">2</SetVar>
注意这里没有使用"urn.."前缀。而且这个方法只在文档库中有效,在列表中是无效的。
8. 批量创建folder:
<Method ID="5212f5e4-0cc6-41b7-824c-4d5ccdf8d865">
<SetList>dac2fbde-f2f6-4adb-a079-f3333395e719</SetList>
<SetVar Name="Cmd">Save</SetVar>
<SetVar Name="ID">New</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#Title">folder1</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#ContentType">Folder</SetVar>
<SetVar Name="owsfileref">/Lists/Version List/folder1</SetVar>
</Method>
其中owsfileref用来设置folder的RootFolder属性,如果不设置这个属性,创建的folder的RootFolder的名字是ID_.000。有的文章建议设置FSObjType属性:
<SetVar Name="FSObjType">1</SetVar>
但是我在SharePoint 2013的环境下没有设置也是可以创建folder的。
9. 批量向folder中添加item:
<Method ID="7727FC54-5A7D-4D59-A141-7FA5A564080B">
<SetList>FE7EB41D-376A-43D1-9EC4-49235BB85788</SetList>
<SetVar Name="Cmd">Save</SetVar>
<SetVar Name="ID">New</SetVar>
<SetVar Name="RootFolder">/sites/subsite/Lists/testlist/testfolder</SetVar>
</Method>
需要指定一个RootFolder属性即可。
11.批量审批
<Method ID="5A3035C3-06DD-48F9-9933-E2A489978ACC">
<SetList>dac2fbde-f2f6-4adb-a079-f3333395e719</SetList>
<SetVar Name="Cmd">Moderate</SetVar>
<SetVar Name="ID">18</SetVar>
<SetVar Name="owsfileref">/shared documents/1.txt</SetVar>
<SetVar Name="owshiddenmodstatus">3</SetVar>
<SetVar Name="urn:schemas-microsoft-com:office:office#_ModerationStatus">0</SetVar>
<SetVar Name="owsitemlevel">2</SetVar>
<SetVar Name="_Level">2</SetVar>
<SetVar Name="owshiddenversion">2</SetVar>
</Method>
12.如果批量更新的item过多,例如20000+,建议分批次处理,每次更新5000个,防止超时。
参考资源:http://stefan-stanev-sharepoint-blog.blogspot.hk/2009/07/tips-for-using-spwebprocessbatchdata.html