您的位置:首页 > 其它

使用WSS的Lists.UpdateListItems()方法之被截断的CAML

2009-03-20 16:29 399 查看
Microsoft的WSS(Windows Sharepoint Services)公开了很多用于访问和管理Sharepoint站点的方法,在调用这些方法时可以通过CAML(Collaborative Application Markup Language)进行一些操作。其中Lists.UpdateListItems()方法提供了用于向Sharepoint List增、删、改数据的方法,但是需要通过CAML语句告诉Sharepoint如何更新数据,有关如何使用CAML以及如何编写CAML进行List数据更新,读者可以参考微软的MSDN文档。

http://msdn.microsoft.com/zh-cn/library/websvclists.lists.updatelistitems.aspx

顺便再给出调用Sharepoint站点的Web Service的地址:
http://Sitename/_vit_bin/lists.asmx?op=UpdateListItems
在使用Lists.UpdateListItems方法时,所使用的用于更新数据的CAML类似于下面这样:

<Batch OnError="Continue">

<Method ID="1" Cmd="New">

<Field Name="Title">Hello<Field>

<Field Name="Document">5</Field>

</Method>

<Method ID="2" Cmd="New">

<Field Name="Title" >World</Field>

<Field Name="Document">5</Field>

</Method>

</Batch>
也就是说我们可以在同一段CAML中批量操作数据。不过最近在实际应用中遇到了一个问题,那就是当我要更新的记录太多,比如20000行,可能我需要写一段特别长的CAML,这个时候当我们在程序中调用Web Service时WSS会给出这样的错误。

Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.

就是说你所使用的CAML语句太长而被自动截断了。细心观察一下,发现被截断的CAML的前半部分已经成功执行到List中了,而后半部分没有被执行,看来我们需要自己动手来处理这个Bug了。最好的办法就是将过长的CAML分批进行处理,一部分一部分地执行。

1 /// <summary>

2 /// Breaks a larg CAML query into smaller batches to avoid the error "Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries."

3 /// </summary>

4 /// <param name="listService">The SharePoint list service to execute the CAML against.</param>

5 /// <param name="listName">The name of the list to execute the CAML against.</param>

6 /// <param name="elementLargeBatch">The CAML batch list of commands to be broken up.</param>

7 /// <param name="intBatchSize">The size of batches to use. If unsure use 300, it seems to work fairly well.</param>

8 /// <returns>Returns the status of each method block posted through the updates parameter and can

9 /// be assigned to a System.Xml.XmlNode object.</returns>

10 public static XmlNode UpdateListItems(SqlClrSharePointSynchronizer.Lists.Lists listService, string listName, XmlElement elementLargeBatch, int intBatchSize)

11 {

12 // calculate useful information

13 int intMethodCount = elementLargeBatch.ChildNodes.Count;

14 int intBatchCount = (int)Math.Ceiling((double)intMethodCount / (double)intBatchSize);

15

16 // prepare xml documents for batches and results

17 XmlDocument xmlDocBatch = new XmlDocument();

18 XmlDocument xmlDocResults = new XmlDocument();

19 XmlElement elementResults = xmlDocResults.CreateElement("Results");

20

21 try

22 {

23 // for each batch

24 for (int intCurrentBatch = 0; intCurrentBatch < intBatchCount; intCurrentBatch++)

25 {

26 int intMethodStart = intCurrentBatch * intBatchSize;

27 int intMethodEnd = Math.Min(intMethodStart + intBatchSize - 1, intMethodCount - 1);

28

29 XmlElement elementSmallBatch = CreateBatch(xmlDocBatch);

30

31 // for each method in the batch

32 for (int intCurrentMethod = intMethodStart; intCurrentMethod <= intMethodEnd; intCurrentMethod++)

33 {

34 XmlElement element = (XmlElement)elementLargeBatch.ChildNodes[intCurrentMethod];

35 elementSmallBatch.AppendChild(xmlDocBatch.ImportNode(element, true));

36 }

37

38 // execute the batch

39 XmlNode nodeBatchResult = listService.UpdateListItems(listName, elementSmallBatch);

40

41 // add the results of the batch into the results xml document

42 foreach (XmlElement elementResult in nodeBatchResult.ChildNodes)

43 {

44 elementResults.AppendChild(xmlDocResults.ImportNode(elementResult, true));

45 }

46

47 // clean up

48 xmlDocBatch.RemoveAll();

49 }

50 }

51 catch (SoapException ex)

52 {

53 if (ex.Detail == null)

54 {

55 throw;

56 }

57

58 //copy the exception detail into the Message so it will be available to SQL.

59 throw new SoapException(ex.Detail.InnerText, ex.Code, ex.Actor, ex.Detail, ex);

60 }

61

62 return (XmlNode)elementResults;

63 }

64

65 /// <summary>

66 /// Create the batch element. e.g. <Batch OnError="Continue"></Batch>

67 /// </summary>

68 /// <param name="xmlDoc">The object of XmlDocument.</param>

69 /// <returns>Return the Batch element.</returns>

70 private static XmlElement CreateBatch(XmlDocument xmlDoc)

71 {

72 XmlElement elementBatch = xmlDoc.CreateElement("Batch");

73 elementBatch.SetAttribute("OnError", "Continue");

74 return elementBatch;

75 }
我在使用的过程中发现超过600行的数据更新就会出现CAML被截断的情况,所以我干脆将intBatchSize设置为300,超过300行的CAML将会被分批执行。在Web Service中使用CAML经常会遇到这样或那样的问题,查询用的CAML问题更多,不过Microsoft在SP对象中对CAML的支持还是不错的,毕竟是经过封装的,使用起来要顺手许多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐