SharePoint 开发指南指示,您不应尝试在单个查询中检索 2000 个以上的项目。如果您的应用程序中可能会出现这种情况,可以考虑在 CAML 查询中使用 RowLimit 元素,以限制客户端对象模型可以为应用程序检索的数据量。有时您必须访问可能包含 2000 个以上项目的列表中的所有项目。如果必须如此,则最好进行分页,一次查看 2000 个项目。本节介绍了使用 ListItemCollectionPosition 属性进行分页的方法。 C# using System; using System.Linq; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists .GetByTitle("Client API Test List"); // First, add 20 items to Client API Test List so that there are // enough records to show paging. ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); for (int i = 0; i < 20; i++) { ListItem listItem = list.AddItem(itemCreateInfo); listItem["Title"] = String.Format("New Item #{0}", i); listItem["Category"] = "Development"; listItem["Estimate"] = i; listItem.Update(); } clientContext.ExecuteQuery(); // This example shows paging through the list ten items at a time. // In a real-world scenario, you would want to limit a page to // 2000 items. ListItemCollectionPosition itemPosition = null; while (true) { CamlQuery camlQuery = new CamlQuery(); camlQuery.ListItemCollectionPosition = itemPosition; camlQuery.ViewXml = @"<View> <ViewFields> <FieldRef Name='Title'/> <FieldRef Name='Category'/> <FieldRef Name='Estimate'/> </ViewFields> <RowLimit>10</RowLimit> </View>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load(listItems); clientContext.ExecuteQuery(); itemPosition = listItems.ListItemCollectionPosition; foreach (ListItem listItem in listItems) Console.WriteLine(" Item Title: {0}", listItem["Title"]); if (itemPosition == null) break; Console.WriteLine(itemPosition.PagingInfo); Console.WriteLine(); } } } 该示例将生成以下输出: Item Title: Write specs for user interface. Item Title: Develop proof-of-concept. Item Title: Write test plan for user interface. Item Title: Validate SharePoint interaction. Item Title: Develop user interface. Item Title: New Item #0 Item Title: New Item #1 Item Title: New Item #2 Item Title: New Item #3 Item Title: New Item #4 Paged=TRUE&p_ID=10 Item Title: New Item #5 Item Title: New Item #6 Item Title: New Item #7 Item Title: New Item #8 Item Title: New Item #9 Item Title: New Item #10 Item Title: New Item #11 Item Title: New Item #12 Item Title: New Item #13 Item Title: New Item #14 Paged=TRUE&p_ID=20 Item Title: New Item #15 Item Title: New Item #16 Item Title: New Item #17 Item Title: New Item #18 Item Title: New Item #19 异步处理 如果您要构建必须附加到可能不可用的 SharePoint 网站的应用程序,或者您必须定期调用可能要花很长时间的查询,则应考虑使用异步处理。这样,当查询在单独的线程中执行时,您的应用程序能够继续响应用户。在主线程中,您可以设置一个计时器。如果查询所花时间长于所需阈值,该计时器可通知您,以便您可以告诉用户查询状态,并在查询最终完成时显示结果。 客户端对象模型的 JavaScript 版本和 Silverlight 版本(在修改用户界面时)都使用异步处理。SharePoint 2010 SDK 中的主题Data Retrieval Overview包含有关如何通过 JavaScript 和 Silverlight 使用异步处理的示例。 在构建基于 .NET Framework 的传统应用程序(如 Windows 窗体或 WPF 应用程序)时,可能需要使用异步处理。以下示例使用 BeginInvoke 方法异步执行查询。请注意,该代码会将一个语句式 lambda 表达式传递给 BeginInvoke 方法,这样便可方便地创建此模式,因为语句式 lambda 表达式可以引用该表达式所在方法中的自动变量。您可以看到语句式 lambda 表达式可以访问 clientContext 变量和 newListCollection 变量。Microsoft Visual C# 闭包使该语言能够按您预期的方式工作。 C# using System; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { AsynchronousAccess asynchronousAccess = new AsynchronousAccess(); asynchronousAccess.Run(); Console.WriteLine("Before exiting Main"); Console.WriteLine(); Console.WriteLine("In a real application, the application can"); Console.WriteLine("continue to be responsive to the user."); Console.WriteLine(); Console.ReadKey(); } } class AsynchronousAccess { delegate void AsynchronousDelegate(); public void Run() { Console.WriteLine("About to start a query that will take a long time."); Console.WriteLine(); ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); ListCollection lists = clientContext.Web.Lists; IEnumerable<List> newListCollection = clientContext.LoadQuery( lists.Include( list => list.Title)); AsynchronousDelegate executeQueryAsynchronously = new AsynchronousDelegate(clientContext.ExecuteQuery); executeQueryAsynchronously.BeginInvoke( arg => { clientContext.ExecuteQuery(); Console.WriteLine("Long running query completed."); foreach (List list in newListCollection) Console.WriteLine("Title: {0}", list.Title); }, null); } } 该示例将生成以下输出。 About to start a query that will take a long time. Before exiting Main In a real application, the application can continue to be responsive to the user. Long running query completed. Title: Announcements Title: Cache Profiles Title: Calendar Title: Client API Test List Title: Content and Structure Reports Title: Content type publishing error log Title: Converted Forms Title: Customized Reports Title: Eric's ToDo List Title: Eric's Wiki Title: Form Templates Title: Links