进行WSS3或MOSS开发的朋友不可避免的要处理各种List的查询,编写类似下面的CAML语句:
<
Where
>
<
And
>
<
And
>
<
Eq
><
FieldRef
Name
=”Title”><Value
Type
=”Text”>Value</Value></Eq>
<Eq
><
FieldRef
Name
=”ContentType”><Value
Type
=”Text”>Product</Value></Eq>
</And
>
<
Eq
><
FieldRef
Name
=”Field1”><Value
Type
=”Text”>Value</Value></Eq>
</And
>
<
Or
>
<
Or
>
<
Eq
><
FieldRef
Name
=”Title”><Value
Type
=”Text”>Value</Value></Eq>
<Eq
><
FieldRef
Name
=”ContentType”><Value
Type
=”Text”>Product</Value></Eq>
</Or
>
<
Eq
><
FieldRef
Name
=”Field1”><Value
Type
=”Text”>Value</Value></Eq>
</Or
>
</
Where
>
痛苦吧? 简单的还好,复杂一点的caml查询绝对会让你晕头转向。
现在网上的解决方案有几种:
1)CAMLBuilder:提供一个Window程序,可以动态生成CAML,然后开发人员可以粘贴进代码代码中。
http://blog.u2u.info/DottextWeb/patrick/archive/2005/05/29/3522.aspx
2)CAML.net : 提供了一个类库,可以如下的编写CAML:
http://www.codeplex.com/camldotnet
string
typeName
=
"
My Content Type
"
;
string
simpleQuery
=
CAML.Query(
CAML.Where(
CAML.Or(
CAML.Eq(
CAML.FieldRef(
"
ContentType
"
),
CAML.Value(typeName)),
CAML.IsNotNull(
CAML.FieldRef(
"
Description
"
)))),
CAML.GroupBy(
true
,
CAML.FieldRef(
"
Title
"
,CAML.SortType.Descending)),
CAML.OrderBy(
CAML.FieldRef(
"
_Author
"
),
CAML.FieldRef(
"
AuthoringDate
"
),
CAML.FieldRef(
"
AssignedTo
"
,CAML.SortType.Ascending))
);
3)还有一位兄弟写了个支持用sql语句形式的caml类库,查询语句如下:
SPWeb web
=
SPContext.Current.Web;
string
queryStr
=
"
SELECT * FROM 通知 WHERE ID>10
"
;
FriendlyQuery query
=
new
FriendlyQuery(web, queryStr);
query.RowLimit
=
100
;
query.Scope
=
FriendlyQuery.QueryScope. AllItemsAndFolders;
SPListItemCollection items
=
query.GetItems();
foreach
(SPListItem i
in
items)
Response.Write(i.Title
+
"
<br/>
"
);
上面的三种方案,个人还是比较喜欢CAML.net的实现,纯代码,但是它的语法不是那么的"优雅"。
以前写过一个数据库ORM工具,见(
DBO),实现了如下的数据查询语法:
QueryExpression expr
=
DboQuery.Select( User.__UserName,Org.__OrgName )
.From
<
User
>
()
.InnerJoin
<
Org
>
().On(User.__OrgId, Org.__OrgId)
.Where(Org.__OrgId
==
2
|
Org.__OrgId
==
3
);
IList
<
RefOrgUser
>
orgs
=
_session.Query
<
RefOrgUser
>
(expr) ;
于是,计划开发类似语法的CAML查询类库--
CodeArt.SharePoint.CAMLQuery.dll。
07年六月份开始开发,已经用到了实际的项目中,实现了几个复杂的查询功能,好东西不敢独享,哈哈,给大家show一下。
(在后面大家可以找到dll的下载链接)
以下的代码示例针对一个列表CAMLList做查询,此列表有如下字段:标题,正文,修改时间。
首先,引用名称空间。
using
System.Data;
using
Microsoft.SharePoint;
using
CodeArt.SharePoint.CAMLQuery;
代码1:查询标题中包含"XXX"的 项目:
QueryField titleField
=
new
QueryField(
"
标题
"
);
SPSite site
=
new
SPSite(
"
http://jyserver:9000
"
);
SPList list
=
site.RootWeb.Lists[
"
CAMLTest
"
];
SPQuery q
=
new
SPQuery ();
q.Query
=
CAMLBuilder.Where( list , titleField.Contains(
"
XXX
"
) );
SPListItemCollection items
=
list.GetItems(q);
int
count
=
items.Count;
代码2:查询标题中包含"XXX"或"YYY"的 项目:
SPList list
=
this
.GetTestList();
ICAMLExpression expr
=
QueryModel.Title.Contains(
"
XXX
"
)
||
QueryModel.Title.Contains(
"
YYY
"
);
PQuery q
=
new
SPQuery();
q.Query
=
CAMLBuilder.Where(list, expr );
SPListItemCollection items
=
list.GetItems(q);
int
count
=
items.Count;
代码3:我们可以创建一个查询模型,类似一个实体类,针对这个类进行查询:
/**/
/// <summary>
/// 查询模型
/// </summary>
class
QueryModel
{
public static FieldRef<QueryModel> Title = new FieldRef<QueryModel>("标题");
public static FieldRef<QueryModel> Body = new FieldRef<QueryModel>("正文");
public static TypeFieldRef<QueryModel, DateTime> ModifyTime = new TypeFieldRef<QueryModel, DateTime>("修改时间");
}
[TestMethod]
public
void
TestModelQuery()
{
SPList list = this.GetTestList();
SPQuery q = new SPQuery();
q.Query = CAMLBuilder.Where( list , QueryModel.Title.Contains("XXX") );
q.ViewFields = CAMLBuilder.ViewFields( list , QueryModel.Title, QueryModel.Body);
SPListItemCollection items = list.GetItems(q);
int count = items.Count;
}
代码4:按照逻辑动态拼接查询,以下示例查询标题中包含"XXX"或"YYY"的 项目,按照
queryByTime
参数,附加修改时间条件:
SPList list
=
this
.GetTestList();
bool
queryByTime
=
true
;
TypedCAMLExpression<QueryModel> expr = QueryModel.Title.Contains("XXX") || QueryModel.Title.Contains("YYY");
if
( queryByTime )
expr
=
expr
&
QueryModel.ModifyTime
>=
DateTime.Now.AddDays(
-
1
)
SPQuery q
=
new
SPQuery();
q.Query
=
CAMLBuilder.Where(list, expr );
SPListItemCollection items
=
list.GetItems(q);
int
count
=
items.Count;
代码5:我们可以用类似sql的强类型语法:
QueryField titleField
=
new
QueryField(
"
标题
"
);
QueryField bodyField
=
new
QueryField(
"
正文
"
);
SPList list
=
this
.GetTestList();
//只查询两个字段
SPListItemCollection result1
=
ListQuery.Select(titleField, bodyField)
.From(list)
.Where(titleField.Contains(
"
XXX
"
))
.GetItems();
int
count
=
result1.Count;
//查询所有字段
SPListItemCollection result2
=
ListQuery.From(list)
.Where(titleField.Contains(
"
XXX
"
))
.GetItems();
int
count2
=
result2.Count;
//直接返回DataTable
DataTable result3
=
ListQuery.Select(titleField,bodyField)
.From(list)
.Where(titleField.Contains(
"
XXX
"
)|
titleField.Contains(
"
YYY
"
)
)
.OrderBy( titleField ,
false
)
.GetDataTable();
int
count3
=
result3.Rows.Count;
下载dll:
https://www.codeplex.com/camlquery
最新版本的接口可能有变化,使用时请参考最新的文档。
附:
原来还有第五种方案: 用 .net3.5的朋友可以试试LINQtoSharePoint,跟o这个.net2.0的好像差不多:
http://www.codeplex.com/LINQtoSharePoint