数据检索概述
上次修改时间: 2015年3月9日
适用范围: SharePoint Foundation 2010
本文内容
查询语法与方法语法
在 ECMAScript 中使用查询字符串
就地加载与可查询加载
如何检索对象
如何更新对象
如何检索列表项
如何更新列表项
异步处理过程
可以使用新的客户端对象模型来检索特定 SharePoint 客户端对象(ClientObject,或者 ECMAScript(JavaScript、JScript) 中的 ClientObject)的属性,或检索子对象及其关联的属性或集合中的子项。对象模型使用显式数据检索语义,在检索正常工作的数据时,必须遵循这些语义。客户端对象模型不保留在客户端上本地检索的数据。
执行数据检索涉及以下过程:
使用 ClientContext() 构造函数 (JavaScript: ClientContext(serverRelativeUrl)) 返回客户端请求的上下文。
使用对象模型指定要检索的对象或要从中检索数据的对象。
通过就地加载或可查询加载来加载对象或集合,就地加载使用 Load<T>(T, []) (JavaScript: load(clientObject)) 方法返回特定的对象、集合或数据;可查询加载使用 LoadQuery() (JavaScript: loadQuery(clientObjectCollection, exp)) 方法返回对象的可枚举集合。
通过在客户端对象模型的 .NET 托管版本中调用同步 ExecuteQuery() 方法执行查询,或者在 Silverlight 版本中,当代码从不修改用户界面 (UI) 的线程执行时,执行查询。在对象模型的 JavaScript 版本中,或者当 Silverlight 版本修改 UI 时,数据检索过程将使用异步回调模型,并且您必须调用 ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) 方法 (JavaScript: executeQueryAsync(succeededCallback, failedCallback)),该方法包括用于处理成功或失败请求的方法参数。当执行查询的方法调用返回(同步或异步)时,您可以访问从中启动查询的对象上的查询结果。
查询语法与方法语法
语言集成查询 (LINQ) 语法的两种形式(查询语法和方法语法)都可在托管客户端对象模型中使用,以加载单个对象、特定对象属性或可枚举对象集合。
备注
在使用 LINQ 对客户端对象模型进行查询时,请记住以下两点:
-
当您使用 LINQ 针对客户端对象模型创建查询时,需使用 LINQ to Objects 而不是 LINQ to SharePoint 提供程序,只有在对服务器对象模型编写代码时,才能使用 LINQ to SharePoint 提供程序。
-
当您的查询旨在从列表中返回部分列表项时,使用 CAML 查询会比使用 LINQ 查询更高效。这是因为,所有列表项都将从内容数据库发送到前端 Web 服务器并加载到内存中。之后,仅应用 LINQ 筛选器。利用 CAML 查询,可在数据库服务器上执行筛选。这一点仅适用于在列表上筛选项目的查询。其他类别的 LINQ 查询(例如,从网站返回部分列表)会更高效。
查询语法只能在 LoadQuery() 方法中使用,并且需要两个步骤:定义查询表达式和检索查询结果。以下代码示例演示了该过程,该示例返回当前网站中具有定义的标题的所有列表。
var query = from list
in clientContext.Web.Lists
where list.Title != null
select list;
var result = clientContext.LoadQuery(query);
clientContext.ExecuteQuery();
Dim query = From list In clientContext.Web.Lists _
Where list.Title IsNot Nothing _
Select list
Dim result = clientContext.LoadQuery(query)
clientContext.ExecuteQuery()
方法语法可与 Load<T>(T, []) 或 LoadQuery() 方法结合使用,并使用 lambda 表达式。以下示例使用方法语法为具有标题的列表定义相同的查询。
clientContext.Load(clientContext.Web,
website => website.Lists.Include(
list => list.Title).Where(
list => list.Title != null));
clientContext.ExecuteQuery();
clientContext.Load(clientContext.Web, _
Function(website) website.Lists.Include( _
Function(list) list.Title).Where( _
Function(list) list.Title IsNot Nothing))
clientContext.ExecuteQuery()
上面的示例演示了如何使用 Include<TSource>(IQueryable<TSource>, []) 方法限制从对象集合返回的属性,这可以提高性能。该查询只返回具有标题的列表的标题。
下面的示例使用查询语法来检索列表中处于非隐藏状态的可筛选字段。
FieldCollection collField = oList.Fields;
var query = from field
in collField
where field.Hidden == false
&& field.Filterable == true
select field;
var result = clientContext.LoadQuery(query);
clientContext.ExecuteQuery();
Dim collField As FieldCollection = oList.Fields
Dim query = From field In collField _
Where field.Hidden = False AndAlso field.Filterable = True _
Select field
Dim result = clientContext.LoadQuery(query)
clientContext.ExecuteQuery()
以下示例执行与上一示例相同的查询,但在 Load<T>(T, []) 方法中使用了方法语法。
clientContext.Load(oList,
list => list.Fields.Where(
field => field.Hidden == false
&& field.Filterable == true));
clientContext.ExecuteQuery();
clientContext.Load(oList, Function(list) list.Fields.Where( _
Function(field) field.Hidden = False _
AndAlso field.Filterable = True))
clientContext.ExecuteQuery()
在 ECMAScript 中使用查询字符串
用于检索对象和数据的 JavaScript 方法不接受 LINQ 语法,但您可以使用字符串表达式来定义基本查询。以下示例使用 load(clientObject) 方法以便只检索特定列表的标题和 ID。
clientContext.load(oList, 'Title' ,'Id');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
在使用列表集合时,可指定 Include 以便只返回每个列表的标题和 ID,如以下示例所示。
clientContext.load(collList, 'Include(Title, Id)');
或者,可以使用与对象或集合关联的 *PropertyNames 类的字段来指定要返回的属性,如以下示例所示:
var propTitle = SP.ListPropertyNames.title;
var propId = SP.ListPropertyNames.id;
clientContext.load(collList, 'Include(' + propTitle + ', ' + propId + ')');
您还可以将 Include 关键字嵌套在所传递的查询字符串中。以下示例使用 loadQuery(clientObjectCollection, exp) 方法检索所有列表的标题,以及所有列表中全部字段的标题和说明。
myListArray = clientContext.loadQuery(collList,
'Include(Title,Fields.Include(Title,Description))');
就地加载与可查询加载
可通过两种方法对客户端对象模型使用基于 LINQ 的查询:通过就地加载和通过可查询加载。可查询加载在另一个结果数组中返回数据,而就地加载在对象本身中返回数据。
就地加载会发出加载对象及其数据的请求,并通过多个请求保留对象标识。可以通过客户端上下文的 Load<T>(T, []) 方法执行就地加载。以下示例加载当前网站的所有列表及其所有默认属性。执行查询后,代码将可以访问整个列表集合和默认的列表属性:
clientContext.Load(clientContext.Web.Lists);
clientContext.ExecuteQuery();
在可查询加载中,查询与返回的结果分隔开。与就地加载不同,在可查询加载中,不会保留对象标识,因此您的代码必须自己维护返回的对象。以下示例使用查询语法返回网站的所有列表。
var query = from list
in clientContext.Web.Lists
select list;
var result = clientContext.LoadQuery(query);
clientContext.ExecuteQuery();
Dim query = From list In clientContext.Web.Lists _
Select list
Dim result = clientContext.LoadQuery(query)
clientContext.ExecuteQuery()
该示例使用 List 对象的 IEnumerable<T> 接口填充结果,您的代码可以使用这些对象,并且必须自己维护这些对象。请注意,context.Web.Lists 保留为空,并且仍然返回计数 0;若要获取列表计数,您必须使用 IEnumerable<T> 接口的 Count()。
如何检索对象
以下示例演示了如何加载对象以访问其属性。由于已就地加载列表对象,因此可以访问列表的所有默认属性。
ClientContext clientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle("Announcements");
clientContext.Load(oList);
clientContext.ExecuteQuery();
Console.WriteLine("Title: {0} Created: {1}", oList.Title, oList.Created);
Dim clientContext As New ClientContext("http://MyServer/sites/MySiteCollection")
Dim oWebsite As Web = clientContext.Web
Dim collList As ListCollection = oWebsite.Lists
Dim oList As List = collList.GetByTitle("Announcements")
clientContext.Load(oList)
clientContext.ExecuteQuery()
Console.WriteLine("Title: {0} Created: {1}", oList.Title, oList.Created)
function retrieveWebSite() {
var clientContext = new SP.ClientContext('/sites/MySiteCollection');
var oWebsite = clientContext.get_web();
var collList = oWebsite.get_lists();
this.oList = collList.getByTitle('Announcements');
clientContext.load(oList);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded(sender, args) {
alert('Title: ' + oList.get_title() + ' Created: ' + oList.get_created());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
在检索特定对象时,有些属性默认情况下不可用。若要访问这些属性,您必须明确加载它们。前面的示例加载一个特定的列表对象,并且可以访问它的两个属性,因为默认情况下该对象上的这两个属性均可用。但是,如果该示例尝试访问默认情况下不可用的属性(如 OnQuickLaunch (JavaScript: onQuickLaunch)),则会返回 PropertyOrFieldNotInitializedException。下表列出了在检索对象时默认情况下不可用的属性。
除了上表中列出的属性外,可通过对象属性访问的父对象或子对象默认情况下不可用。因此,在前面的示例中添加 oList.Items.Count 将始终在控制台中显示 0,而不是实际的项数(如果有),这是因为没有在 Load<T>(T, []) 方法 (JavaScript: load(clientObject)) 中专门请求列表项集合。
若要访问在返回对象时默认情况下不可用的属性,您必须明确请求属性。前面的 Load<T>(T, []) (JavaScript: load(clientObject)) 方法调用的以下修订版使 OnQuickLaunch (JavaScript: onQuickLaunch) 变得可用。
clientContext.Load(oList,
list => list.Title,
list => list.Created,
list => list.OnQuickLaunch);
clientContext.Load(oList, _
Function(list) list.Title, _
Function(list) list.Created, _
Function(list) list.OnQuickLaunch)
clientContext.load(oList, 'Title', 'Created', 'OnQuickLaunch');
在托管或 Silverlight 对象模型中,如果您使用对象集合,则应使用 IncludeWithDefaultProperties<TSource>(IQueryable<TSource>, []) 方法,以包括在加载每个列表时默认情况下不可用的属性。
备注
JavaScript 对象模型没有与 IncludeWithDefaultProperties<TSource>(IQueryable<TSource>, []) 方法等效的方法。
以下示例显示的有关网站中每个列表的信息与前面示例中显示的信息相同。
ClientContext clientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
clientContext.Load(collList,
lists => lists.IncludeWithDefaultProperties(
list => list.OnQuickLaunch));
clientContext.ExecuteQuery();
foreach (List oList in collList)
{
Console.WriteLine("Title: {0} Created: {1} QuickLaunch: {2}", oList.Title, oList.Created, oList.OnQuickLaunch);
}
Dim clientContext As New ClientContext("http://MyServer/sites/MySiteCollection")
Dim oWebsite As Web = clientContext.Web
Dim collList As ListCollection = oWebsite.Lists
clientContext.Load(collList, _
Function(lists) lists.IncludeWithDefaultProperties( _
Function(list) list.OnQuickLaunch))
clientContext.ExecuteQuery()
Dim oList As List
For Each oList In collList
Console.WriteLine("Title: {0} Created: {1} QuickLaunch: {2}", oList.Title, oList.Created, oList.OnQuickLaunch)
Next oList
如何更新对象
通过客户端对象模型修改对象的原理与通过服务器对象模型修改对象的原理类似。在这两种情况下,您都必须调用 Update 方法。不过,在使用客户端对象模型时,只有在加载对象并调用 ExecuteQuery() 或 ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) (JavaScript: executeQueryAsync(succeededCallback, failedCallback)) 之后,所做更改才会生效。以下示例更改了所加载列表的说明。
ClientContext clientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle("My List");
oList.Description = "Changed description...";
oList.Update();
clientContext.ExecuteQuery();
Dim clientContext As New ClientContext("http://MyServer/sites/MySiteCollection")
Dim oWebsite As Web = clientContext.Web
Dim collList As ListCollection = oWebsite.Lists
Dim oList As List = collList.GetByTitle("My List")
oList.Description = "Changed description..."
oList.Update()
clientContext.ExecuteQuery()
function updateList() {
var clientContext = new SP.ClientContext('/sites/MySiteCollection');
var oWebsite = clientContext.get_web();
var collList = oWebsite.get_lists();
this.oList = collList.getByTitle('My List');
oList.set_title('Changed description...');
oList.update();
clientContext.load(oList);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
alert(oList.get_title() + ' created.');
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
请注意,在前面的示例中,修改对象并不需要在客户端上加载该对象。
如何检索列表项
若要检索大量列表项,使用协作应用程序标记语言 (CAML) 查询指定要返回的项最为高效。可使用 CamlQuery 类 (JavaScript: CamlQuery) 定义该查询,然后将该查询传递给 GetItems(CamlQuery) 方法 (JavaScript: getItems(query))。
以下示例使用 CamlQuery 类 (JavaScript: CamlQuery) 来返回列表中 ID 小于 100 的前 50 项。Load<T>(T, []) 方法指定 IncludeWithDefaultProperties<TSource>(IQueryable<TSource>, []) 以检索 DisplayName。
ClientContext clientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle("My List");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><Leq>" +
"<FieldRef Name='ID'/><Value Type='Number'>100</Value>" +
"</Leq></Where></Query><RowLimit>50</RowLimit></View>";
ListItemCollection collListItem = oList.GetItems(camlQuery);
clientContext.Load(collListItem,
items => items.IncludeWithDefaultProperties(
item=>item.DisplayName));
clientContext.ExecuteQuery();
foreach (ListItem oListItem in collListItem)
{
Console.WriteLine("ID: {0} Display name: {1}", oListItem.Id, oListItem.DisplayName);
}
Dim clientContext As New ClientContext("http://MyServer/sites/MySiteCollection")
Dim oWebsite As Web = clientContext.Web
Dim collList As ListCollection = oWebsite.Lists
Dim oList As List = collList.GetByTitle("My List")
Dim camlQuery As New CamlQuery()
camlQuery.ViewXml = "<View><Query><Where><Leq>" + _
"<FieldRef Name='ID'/><Value Type='Number'>100</Value>" + _
"</Leq></Where></Query><RowLimit>50</RowLimit></View>"
Dim collListItem As ListItemCollection = oList.GetItems(camlQuery)
clientContext.Load(collListItem, _
Function(items) items.IncludeWithDefaultProperties( _
Function(item) item.DisplayName))
clientContext.ExecuteQuery()
Dim oListItem As ListItem
For Each oListItem In collListItem
Console.WriteLine("ID: {0} Display name: {1}", oListItem.Id, oListItem.DisplayName)
Next oItem
由于 JavaScript 对象模型不具有 IncludeWithDefaultProperties<TSource>(IQueryable<TSource>, []) 方法,因此以下示例将 Include 与 load(clientObject) 方法结合使用,以指定检索每个列表项的 ID 和显示名称。
function retrieveListItems() {
var clientContext = new SP.ClientContext('/sites/MySiteCollection');
var oList = clientContext.get_web().get_lists().getByTitle('My List');
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><Where><Leq>' +
'<FieldRef Name=\'ID\'/><Value Type=\'Number\'>100</Value>' +
'</Leq></Where></Query><RowLimit>50</RowLimit></View>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem, 'Include(Id, DisplayName)');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded(sender, args) {
var listItemInfo = '';
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
listItemInfo += '\nID: ' + oListItem.get_id() +
'\nDisplay name: ' + oListItem.get_displayName();
}
alert(listItemInfo.toString());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
如何更新列表项
若要修改列表项,您可以指定通过索引器来更改列值,并且就像对待其他对象那样,在调用 ExecuteQuery() 或 ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) (JavaScript: executeQueryAsync(succeededCallback, failedCallback)) 之前调用 Update() (JavaScript: update())。以下示例更改具有指定 ID 的项的标题。
ClientContext clientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle("My List");
ListItem oItem = oList.GetItemById(5);
oItem["Title"] = "Hello World";
oItem.Update();
clientContext.ExecuteQuery();
Dim clientContext As New ClientContext("http://MyServer/sites/MySiteCollection")
Dim oWebsite As Web = clientContext.Web
Dim collList As ListCollection = oWebsite.Lists
Dim oList As List = collList.GetByTitle("My List")
Dim oItem As ListItem = oList.GetItemById(5)
oItem("Title") = "Hello World"
oItem.Update()
clientContext.ExecuteQuery()
function updateListItem() {
var clientContext = new SP.ClientContext('sites/MySiteCollection');
var oList = clientContext.get_web().get_lists().getByTitle('My List');
this.oListItem = oList.getItemById(5);
oListItem.set_item('Title', 'Hello World');
oListItem.update();
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
alert('Item updated.');
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
异步处理过程
对象模型的 JavaScript 版本和 Silverlight 版本(在修改 UI 时)都使用异步处理过程。因此,ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) 方法 (JavaScript: executeQueryAsync(succeededCallback, failedCallback)) 会为回调方法传递委托,以处理查询成功和失败情况。当该异常方法处理完成后,将调用指定的回调方法,并且客户端将从服务器检索数据。若要执行使用 JavaScript 或 Silverlight 对象模型的查询,应定义一个与回调方法具有相同签名的委托,并通过在 ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) (JavaScript: executeQueryAsync(succeededCallback, failedCallback)) 中将该委托作为参数传递来扩展调用路径。
以下示例演示了 JavaScript 和 Silverlight 中的异步处理过程。第一个方法 retrieveWebsite 获取当前网站的对象,该对象将可供指定的回调方法 onQuerySucceeded 使用。对于该回调方法,会在 ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) (JavaScript: executeQueryAsync(succeededCallback, failedCallback)) 中传递委托。该回调方法获取并设置所检索的网站对象的标题,并再次调用查询执行方法以使更新生效。
var oWebsite;
var clientContext;
function retrieveWebsite()
{
clientContext = SP.ClientContext.get_current();
oWebsite = clientContext.get_web();
clientContext.load(oWebsite);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed);
}
function onQuerySucceeded()
{
oWebsite.set_title(oWebsite.get_title() + " changed in ECMAScript.");
oWebsite.update();
clientContext.executeQueryAsync();
}
以下示例演示了如何使用 Silverlight 对象模型按类似方法设置网站标题。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.SharePoint.Client;
namespace Microsoft.SDK.SharePointServices.Samples
{
public partial class MainPage : UserControl
{
ClientContext clientContext;
Web oWebsite;
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
clientContext = ClientContext.Current;
oWebsite = clientContext.Web;
clientContext.Load(oWebsite,
website=>website.Title);
clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
}
private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgs args)
{
UpdateUIMethod updateUI = ChangeTitle;
this.Dispatcher.BeginInvoke(updateUI);
}
private void ChangeTitle()
{
oWebsite.Title = oWebsite.Title + " changed in Silverlight.";
oWebsite.Update();
clientContext.ExecuteQueryAsync(onTitleChanged, onQueryFailed);
}
private void onTitleChanged(object sender, ClientRequestSucceededEventArgs args)
{
UpdateUIMethod updateUI = DisplayTitle;
this.Dispatcher.BeginInvoke(updateUI);
}
private void DisplayTitle()
{
MessageBox.Show("Title changed to " + oWebsite.Title);
}
private void onQueryFailed(object sender, ClientRequestFailedEventArgs args)
{
MessageBox.Show("Request failed. " + args.Message + "\n" + args.StackTrace);
}
private delegate void UpdateUIMethod();
}
}
JavaScript 和 Silverlight 示例都使用客户端上下文的 Current 属性 (JavaScript: current) 来指定当前请求上下文,而不是使用 ClientContext(String) 构造函数 (JavaScript: ClientContext(serverRelativeUrl)) 并指定 URL。
有关 SharePoint Foundation Silverlight 对象模型上下文中数据检索的其他示例和信息,请参阅使用 Silverlight 对象模型。
请参阅
概念
其他资源
使用 SharePoint Foundation 2010 托管客户端对象模型