进行WSS3或MOSS开发的朋友不可避免的要处理各种List的查询,编写类似下面的CAML语句:

WSS3.0开发--你还在为写CAML痛苦吗?<Where>
WSS3.0开发--你还在为写CAML痛苦吗?
<And>
WSS3.0开发--你还在为写CAML痛苦吗? 
<And>
WSS3.0开发--你还在为写CAML痛苦吗?  
<Eq><FieldRef Name=”Title”><Value Type=”Text”>Value</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗?  
<Eq><FieldRef Name=”ContentType”><Value Type=”Text”>Product</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗? 
</And>
WSS3.0开发--你还在为写CAML痛苦吗? 
<Eq><FieldRef Name=”Field1”><Value Type=”Text”>Value</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗?
</And> 
WSS3.0开发--你还在为写CAML痛苦吗?
<Or>
WSS3.0开发--你还在为写CAML痛苦吗? 
<Or>
WSS3.0开发--你还在为写CAML痛苦吗?  
<Eq><FieldRef Name=”Title”><Value Type=”Text”>Value</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗?  
<Eq><FieldRef Name=”ContentType”><Value Type=”Text”>Product</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗? 
</Or>
WSS3.0开发--你还在为写CAML痛苦吗? 
<Eq><FieldRef Name=”Field1”><Value Type=”Text”>Value</Value></Eq>
WSS3.0开发--你还在为写CAML痛苦吗?
</Or> 
WSS3.0开发--你还在为写CAML痛苦吗?
</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

WSS3.0开发--你还在为写CAML痛苦吗?string typeName = "My Content Type";
WSS3.0开发--你还在为写CAML痛苦吗?
string simpleQuery =
WSS3.0开发--你还在为写CAML痛苦吗?    CAML.Query(
WSS3.0开发--你还在为写CAML痛苦吗?        CAML.Where(
WSS3.0开发--你还在为写CAML痛苦吗?            CAML.Or(
WSS3.0开发--你还在为写CAML痛苦吗?                CAML.Eq(
WSS3.0开发--你还在为写CAML痛苦吗?                    CAML.FieldRef(
"ContentType"), 
WSS3.0开发--你还在为写CAML痛苦吗?                    CAML.Value(typeName)),
WSS3.0开发--你还在为写CAML痛苦吗?                CAML.IsNotNull(
WSS3.0开发--你还在为写CAML痛苦吗?                    CAML.FieldRef(
"Description")))),
WSS3.0开发--你还在为写CAML痛苦吗?        CAML.GroupBy(
WSS3.0开发--你还在为写CAML痛苦吗?            
true,
WSS3.0开发--你还在为写CAML痛苦吗?            CAML.FieldRef(
"Title",CAML.SortType.Descending)),
WSS3.0开发--你还在为写CAML痛苦吗?        CAML.OrderBy(
WSS3.0开发--你还在为写CAML痛苦吗?            CAML.FieldRef(
"_Author"),
WSS3.0开发--你还在为写CAML痛苦吗?            CAML.FieldRef(
"AuthoringDate"),
WSS3.0开发--你还在为写CAML痛苦吗?            CAML.FieldRef(
"AssignedTo",CAML.SortType.Ascending))
WSS3.0开发--你还在为写CAML痛苦吗?    );


3)还有一位兄弟写了个支持用sql语句形式的caml类库,查询语句如下:

WSS3.0开发--你还在为写CAML痛苦吗?SPWeb web = SPContext.Current.Web;
WSS3.0开发--你还在为写CAML痛苦吗?
string queryStr = "SELECT * FROM 通知 WHERE ID>10";
WSS3.0开发--你还在为写CAML痛苦吗?FriendlyQuery query 
= new FriendlyQuery(web, queryStr);
WSS3.0开发--你还在为写CAML痛苦吗?query.RowLimit 
= 100;
WSS3.0开发--你还在为写CAML痛苦吗?query.Scope 
= FriendlyQuery.QueryScope. AllItemsAndFolders;
WSS3.0开发--你还在为写CAML痛苦吗?SPListItemCollection items 
= query.GetItems();
WSS3.0开发--你还在为写CAML痛苦吗?
foreach(SPListItem i in items)
WSS3.0开发--你还在为写CAML痛苦吗?    Response.Write(i.Title 
+ "<br/>");

上面的三种方案,个人还是比较喜欢CAML.net的实现,纯代码,但是它的语法不是那么的"优雅"。
以前写过一个数据库ORM工具,见(DBO),实现了如下的数据查询语法:

WSS3.0开发--你还在为写CAML痛苦吗?QueryExpression expr =WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?             DboQuery.Select( User.__UserName,Org.__OrgName )WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?             .From
<User>()WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?             .InnerJoin
<Org>().On(User.__OrgId, Org.__OrgId)WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?             .Where(Org.__OrgId 
== 2 | Org.__OrgId == 3);WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗? IList
<RefOrgUser> orgs = _session.Query<RefOrgUser>(expr) ;

于是,计划开发类似语法的CAML查询类库--CodeArt.SharePoint.CAMLQuery.dll。
07年六月份开始开发,已经用到了实际的项目中,实现了几个复杂的查询功能,好东西不敢独享,哈哈,给大家show一下。
(在后面大家可以找到dll的下载链接)
以下的代码示例针对一个列表CAMLList做查询,此列表有如下字段:标题,正文,修改时间。

首先,引用名称空间。

WSS3.0开发--你还在为写CAML痛苦吗?using System.Data;
WSS3.0开发--你还在为写CAML痛苦吗?
using Microsoft.SharePoint;
WSS3.0开发--你还在为写CAML痛苦吗?
using CodeArt.SharePoint.CAMLQuery;

代码1:查询标题中包含"XXX"的 项目:

WSS3.0开发--你还在为写CAML痛苦吗?  QueryField titleField = new QueryField("标题");
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  SPSite site 
= new SPSite("http://jyserver:9000");
WSS3.0开发--你还在为写CAML痛苦吗?  SPList list 
=  site.RootWeb.Lists["CAMLTest"];
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?   SPQuery q 
= new SPQuery ();WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?   q.Query 
= CAMLBuilder.Where( list , titleField.Contains("XXX") );
WSS3.0开发--你还在为写CAML痛苦吗?           
WSS3.0开发--你还在为写CAML痛苦吗?   SPListItemCollection items 
= list.GetItems(q);WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  
int count = items.Count;         

代码2:查询标题中包含"XXX"或"YYY"的 项目:

WSS3.0开发--你还在为写CAML痛苦吗? SPList list = this.GetTestList();
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  ICAMLExpression expr 
= QueryModel.Title.Contains("XXX"|| QueryModel.Title.Contains("YYY");            
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  PQuery q 
= new SPQuery();WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  q.Query 
= CAMLBuilder.Where(list, expr );
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  SPListItemCollection items 
= list.GetItems(q);WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗? 
int count = items.Count;

代码3:我们可以创建一个查询模型,类似一个实体类,针对这个类进行查询:

        }

代码4:按照逻辑动态拼接查询,以下示例查询标题中包含"XXX"或"YYY"的 项目,按照queryByTime 参数,附加修改时间条件:

WSS3.0开发--你还在为写CAML痛苦吗? SPList list = this.GetTestList();
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗? 
bool queryByTime = true ;
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?  TypedCAMLExpression<QueryModel> expr = QueryModel.Title.Contains("XXX") || QueryModel.Title.Contains("YYY");
 
WSS3.0开发--你还在为写CAML痛苦吗?        
WSS3.0开发--你还在为写CAML痛苦吗? 
if( queryByTime )
WSS3.0开发--你还在为写CAML痛苦吗?        expr 
= expr & QueryModel.ModifyTime >= DateTime.Now.AddDays(-1)
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?   SPQuery q 
= new SPQuery();WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?   q.Query 
= CAMLBuilder.Where(list, expr );
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?   SPListItemCollection items 
= list.GetItems(q);WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗? 
int count = items.Count;

代码5:我们可以用类似sql的强类型语法:

WSS3.0开发--你还在为写CAML痛苦吗? QueryField titleField = new QueryField("标题");
WSS3.0开发--你还在为写CAML痛苦吗? QueryField bodyField 
= new QueryField("正文");
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?            SPList list 
= this.GetTestList();
WSS3.0开发--你还在为写CAML痛苦吗?          //只查询两个字段
WSS3.0开发--你还在为写CAML痛苦吗?            SPListItemCollection result1 
=
WSS3.0开发--你还在为写CAML痛苦吗?                ListQuery.Select(titleField, bodyField)
WSS3.0开发--你还在为写CAML痛苦吗?                        .From(list)
WSS3.0开发--你还在为写CAML痛苦吗?                        .Where(titleField.Contains(
"XXX"))
WSS3.0开发--你还在为写CAML痛苦吗?                        .GetItems();
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?            
int count = result1.Count;
WSS3.0开发--你还在为写CAML痛苦吗?          //查询所有字段
WSS3.0开发--你还在为写CAML痛苦吗?            SPListItemCollection result2 
=
WSS3.0开发--你还在为写CAML痛苦吗?                ListQuery.From(list)
WSS3.0开发--你还在为写CAML痛苦吗?                         .Where(titleField.Contains(
"XXX"))
WSS3.0开发--你还在为写CAML痛苦吗?                         .GetItems();
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?            
int count2 = result2.Count;
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?          //直接返回DataTable
WSS3.0开发--你还在为写CAML痛苦吗?            DataTable result3 
=
WSS3.0开发--你还在为写CAML痛苦吗?                ListQuery.Select(titleField,bodyField)
WSS3.0开发--你还在为写CAML痛苦吗?                        .From(list)
WSS3.0开发--你还在为写CAML痛苦吗?                         .Where(titleField.Contains(
"XXX")|titleField.Contains("YYY"))
WSS3.0开发--你还在为写CAML痛苦吗?                         .OrderBy( titleField , 
false )
WSS3.0开发--你还在为写CAML痛苦吗?                         .GetDataTable();
WSS3.0开发--你还在为写CAML痛苦吗?
WSS3.0开发--你还在为写CAML痛苦吗?            
int count3 = result3.Rows.Count;


下载dll: https://www.codeplex.com/camlquery

最新版本的接口可能有变化,使用时请参考最新的文档。

附:
原来还有第五种方案: 用 .net3.5的朋友可以试试LINQtoSharePoint,跟o这个.net2.0的好像差不多:
http://www.codeplex.com/LINQtoSharePoint





相关文章: