程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 使用WSS的Lists.UpdateListItems()方法之被截斷的CAML

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

編輯:關於.NET

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. &lt;Batch OnError="Continue"&gt;&lt;/Batch&gt;
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的支持還是不錯的,畢竟是經過封裝的,使 用起來要順手許多。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved