zoukankan      html  css  js  c++  java
  • 使用WSS的Lists.UpdateListItems()方法之被截断的CAML

        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的支持还是不错的,毕竟是经过封装的,使用起来要顺手许多。
  • 相关阅读:
    Spring IOC知识点一网打尽
    Spring中-IOC-Bean的初始化-循环依赖的解决
    原型模式(Prototype)
    生成器模式
    工厂模式
    单例模式
    查询性能优化
    索引
    sql游标的使用入门
    js和C#中的编码和解码
  • 原文地址:https://www.cnblogs.com/jaxu/p/1417792.html
Copyright © 2011-2022 走看看