进行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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述