首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WSS Lists.UpdateListItems 批量處理:解決 CAML 過長被截斷問題

     編輯:關於.NET

Windows SharePoint Services (WSS) 的 Lists.UpdateListItems 方法支援透過 CAML 批量新增/修改/刪除列表項目。但當批量資料過大(約超過 600 筆)時,CAML XML 過長會導致伺服器端 SQL 解析錯誤:
"Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries."
且前半部資料已寫入、後半部失敗,造成資料不一致。本文提供分批處理的通用解決方案。

問題重現

典型批量 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"> ... </Method>
</Batch>

當 <Method> 節點過多,WSS 內部 SQL 產生超過巢狀層級限制,導致 XML 被截斷執行。

分批處理核心演算法

將大型 <Batch> 依指定批次大小 (建議 300) 拆分為多個小批次,循環呼叫 Web Service,最後合併結果。

完整實現代碼

/// <summary>
/// 將大型 CAML 批次拆分執行,避免 SQL 巢狀過深錯誤
/// </summary>
public static XmlNode UpdateListItems(Lists listService, string listName, XmlElement elementLargeBatch, int batchSize) {
    // 1. 計算分批資訊
    int methodCount = elementLargeBatch.ChildNodes.Count;
    int batchCount = (int)Math.Ceiling((double)methodCount / batchSize);

    // 2. 準備結果文檔
    XmlDocument xmlDocResults = new XmlDocument();
    XmlElement elementResults = xmlDocResults.CreateElement("Results");

    try {
        for (int currentBatch = 0; currentBatch < batchCount; currentBatch++) {
            int methodStart = currentBatch * batchSize;
            int methodEnd = Math.Min(methodStart + batchSize - 1, methodCount - 1);

            // 3. 建立小批次 Batch 元素
            XmlDocument xmlDocBatch = new XmlDocument();
            XmlElement elementSmallBatch = CreateBatch(xmlDocBatch);

            // 4. 複製 Method 節點到小批次
            for (int i = methodStart; i <= methodEnd; i++) {
                XmlElement methodNode = (XmlElement)elementLargeBatch.ChildNodes[i];
                elementSmallBatch.AppendChild(xmlDocBatch.ImportNode(methodNode, true));
            }

            // 5. 執行批次呼叫
            XmlNode nodeBatchResult = listService.UpdateListItems(listName, elementSmallBatch);

            // 6. 合併結果
            foreach (XmlElement resultNode in nodeBatchResult.ChildNodes) {
                elementResults.AppendChild(xmlDocResults.ImportNode(resultNode, true));
            }
        }
    } catch (SoapException ex) {
        if (ex.Detail == null) throw;
        // 保留原始異常詳情
        throw new SoapException(ex.Detail.InnerText, ex.Code, ex.Actor, ex.Detail, ex);
    }

    return elementResults;
}

/// <summary> 建立標準 Batch 元素 </summary>
private static XmlElement CreateBatch(XmlDocument xmlDoc) {
    XmlElement batch = xmlDoc.CreateElement("Batch");
    batch.SetAttribute("OnError", "Continue");
    return batch;
}

關鍵設計點

  1. 批次大小建議 300:實測超過 600 即報錯,300 留有安全邊際。
  2. XmlDocument.ImportNode:跨文檔複製節點必須使用 ImportNode(node, true) 深度複製,否則會拋出「節點屬於不同文檔」異常。
  3. 結果合併:統一用 <Results> 根元素包裹所有批次返回的 <Result> 節點,保持呼叫端介面一致。
  4. 異常保留堆疊:捕獲 SoapException 重新拋出時攜帶原始 Detail,便於上層診斷。
  5. 記憶體釋放:每批次結束呼叫 xmlDocBatch.RemoveAll() 釋放臨時文檔資源。

擴展建議

  • 將 batchSize 設為可配置參數,適應不同 WSS 版本/補丁限制。
  • 加入重試機制:網路抖動導致單批次失敗時自動重試 N 次。
  • 支援異步/並行批次執行(需注意 SharePoint 節流限制)。
  • 查詢類 CAML (GetListItems) 同樣存在長度限制,可複用此分頁邏輯。

此方案已在生產環境穩定運行處理 20,000+ 筆資料同步,有效規避 WSS CAML 長度硬傷,是 SharePoint Web Service 批量操作的標準最佳實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved