SharePoint 2010自带了一个开箱即用的WCF服务——ListData。本博文中,我们将一步一步的学习如何使用ListData.svc。
准备工作
- 创建一个网站,包含两个列表,分别是 客户和城市。为列表填写一些列表项。客户列表应包含一个名为城市的栏,作为查阅项关联到城市列表。
城市列表:

客户列表:

- 创建一个控制台应用程序(实际上什么类型的程序都无所谓),添加一个引用到WCF服务:

注意:在本例中我把引用命名为ListDataService。ListData服务位于虚拟目录/_vti_bin/listdata.svc
开始使用
现在,我们的引用已经建立好了,你需要对其进行实例化。在本例中,我使用了一个全局静态成员变量,以便稍后再其他方法中调用:
static
ListDataService.工作组网站DataContext
Ctx
=
null
;
static
void
Main(
string
[] args)
{
Ctx
=
new
ListDataService.工作组网站DataContex
t
(
new
U
r
i(
"
http://sp2010u/it/_vti_bin/listdata.svc
"
));
Ctx.Credentials
=
System.Net.CredentialCache.DefaultCredentials;
接下来,你就可以开始查询数据了:
static
void
ListCustomerAndCityDetails()
{
var CustomerResults
=
(from Customer
in
Ctx.客户
where
Customer.城市
!=
null
&&
Customer.城市.国家
!=
null
select
new
{
CustomerName
=
Customer.客户,
CityName
=
Customer.城市.城市,
CountryName
=
Customer.城市.国家
});
foreach
(var CustomerResult
in
CustomerResults)
{
Console.WriteLine(
"
客户 {0} 生活在 {2} 的 {1}
"
,
CustomerResult.CustomerName,
CustomerResult.CityName,
CustomerResult.CountryName);
}
}
static
void
ListCustomers()
{
var CustomerResults
=
(from Customer
in
Ctx.客户
select Customer);
foreach
(var CustomerResult
in
CustomerResults)
{
Console.WriteLine(
"
{1} - 客户 {0}
"
, CustomerResult.客户,CustomerResult.Id);
}
}
你也可以执行写操作,比如添加数据:
static
void
AddCustomer(
string
cityname,
string
customername)
{
var CustomerCity
=
Ctx.城市.Where(v
=>
v.城市
==
cityname).FirstOrDefault();
if
(CustomerCity
==
null
)
{
CustomerCity
=
BuildNewCity(cityname);
}
ListDataService.客户Item Client
=
new
ListDataService.客户Item();
Client.城市Id
=
CustomerCity.Id;
Client.城市
=
CustomerCity;
Client.客户
=
customername;
Ctx.AddTo客户(Client);
Ctx.SaveChanges();
}
调用类似AddTo实体名的方法和SaveChanges()方法就可以完成新建列表项的操作。
删除数据:
static
void
DeleteCustomer(
int
IdClient)
{
try
{
Ctx.DeleteObject(Ctx.客户.Where(c
=>
c.Id
==
IdClient).FirstOrDefault());
Ctx.SaveChanges();
}
catch
(DataServiceQueryException)
{
Console.WriteLine(
"
找不到该客户!
"
);
}
}
调用DataServiceContext的DeleteObject和SaveChanges方法就可以完成删除指定项的操作。
接下来是更新数据:
static
void
ModifyCustomerSetNewCity(
int
idclient,
string
newcity)
{
var TargetCustomer
=
Ctx.客户.Where(c
=>
c.Id
==
idclient).FirstOrDefault();
if
(TargetCustomer
==
null
)
throw
new
ApplicationException(
"
目标客户不存在!
"
);
var CustomerCity
=
Ctx.城市.Where(v
=>
v.城市
==
newcity).FirstOrDefault();
if
(CustomerCity
==
null
)
{
CustomerCity
=
BuildNewCity(newcity);
}
TargetCustomer.城市
=
CustomerCity;
TargetCustomer.城市Id
=
CustomerCity.Id;
Ctx.UpdateObject(TargetCustomer);
Ctx.SaveChanges();
}
private
static
ListDataService.城市Item BuildNewCity(
string
cityname)
{
ListDataService.城市Item NewCity
=
new
ListDataService.城市Item()
{
城市
=
cityname
};
Ctx.AddTo城市(NewCity);
Ctx.SaveChanges();
return
Ctx.城市.Where(v
=>
v.城市
==
cityname).FirstOrDefault();
}
这里你需要在调用SaveChanges前调用UpdateObject 方法。其中,你可能已经注意到了,给查阅项设置值时,你必须同时指定查阅项本身的值和一个查阅项 ID。本例中是Client.City和Client.CityID。如果在SPLINQ中就不用这样了...
ListCustomerAndCityDetails的执行结果:
通过Fiddler查看一下这个查询对应的类REST HTTP请求,如下图所示:

点击查看大图
其中的GET部分为:
http://sp2010u/it/_vti_bin/listdata.svc/%E5%AE%A2%E6%88%B7()?$filter=(%E5%9F%8E%E5%B8%82%20ne%20null)%20and%20(%E5%9F%8E%E5%B8%82/%E5%9B%BD%E5%AE%B6%20ne%20null)&$expand=%E5%9F%8E%E5%B8%82&$select=%E5%AE%A2%E6%88%B7,%E5%9F%8E%E5%B8%82/%E5%9F%8E%E5%B8%82,%E5%9F%8E%E5%B8%82/%E5%9B%BD%E5%AE%B6
进行一下UTF-8转码后:
http://sp2010u/it/_vti_bin/listdata.svc/客户()?$filter=(城市 ne null) and (城市/国家 ne null)&$expand=城市&$select=客户,城市/城市,城市/国家
注意到,filter指定了获取客户数据的查询条件,expand指定了还需要从城市列表中获取数据。语法很简单,我们可以方便的在自己的代码中生成类似的查询url。完整的语法请参考MSDN。
---2011/4/23更新---
看到SharePoint in Pictures上的一张SharePoint 2010 REST Service语法图,很不错。

参考资料
Querying,Updating data using a WCF reference to ListData.svc from a console program
Tip of the week - Using the WCF service reference to generate REST-LIKE queries