CAMLBuilder 表达式






4.70/5 (13投票s)
使用表达式以编程方式构建 CAML 查询。
使用 CAMLBuilder.Expressions 构建 CAML 查询
本文介绍了一种解决方案,可用于以非常简单的方式以编程方式构造复杂的 Sharepoint CAML 查询。
解决方案的类图
背景
如果您曾经处理过 Sharepoint 并不得不使用 CAML 查询,您可能会发现有时组合查询是多么痛苦,尤其是在代码中。
参数化固定查询
如果您不想最后连接多个字符串片段,您可以使用流行的工具U2U Caml Query Builder(http://www.u2u.net)首先设计您的查询,然后对其进行参数化,这样您就可以轻松地将其与任何参数集一起使用。
任意查询
然而,前面的方法不幸地仅适用于固定查询。
如果查询是动态构建的,这意味着构建查询所需的条件集只能在运行时确定,您就无法拥有固定的参数化查询,因为在这种情况下查询本身会发生变化。您仍然可以根据任何条件在运行时连接查询片段(条件),但这正是我们想要避免的。
此外,CAML 语言本身使得构建查询更加困难,因为例如,一个运算符只能有两个操作数,因此您需要根据您拥有的条件数量以不同的方式构建查询。
想象一个场景,您想显示一个已过滤的 Sharepoint 列表,其中过滤条件由用户定义。有时您可能只需要一个过滤器,有时需要多个,或者根本不需要过滤器。
- 如果您有一个过滤器,您不需要 <And> 运算符,只需在查询中有一个条件即可。
- 如果您有两个过滤器,您需要 <And> 运算符并在其下放置两个条件。
- 如果您有多个过滤器,您需要 <And> 运算符并在其下放置条件,但由于运算符只能接受两个操作数,您不能只将所有必需的条件放在 <And> 下,而是需要添加一个内部 <And>,这会引导您构建一个递归。
请参阅以下示例。
介绍 CAMLBuilder 表达式
CAML Builder Expressions 为上述问题提供了一个简单的解决方案。您可以使用 Expressions API 构建任意表达式树,然后简单地获取生成的 CAML 查询结果。
有两种表达式:(请参阅:类图)
- 条件
- 运算符
标准
Criteria 定义了字段上的简单条件。它可以是 Simple Criteria 或 Condition Criteria。
Simple 只获取 FieldName,而 Condition 获取 FieldName、FieldType 和 Value 以将字段值与进行比较。
支持的条件类型
简单
- IsNull
- IsNotNull
条件
- Eq (等于)
- Neq (不等于)
- Gt (大于)
- Geq (大于等于)
- Lt (小于)
- Leq (小于等于)
- BeginsWith
- Contains
- DateRangesOverlap
运算符
Operator 定义了一个由多个 Criterias 或 Operators 组成的复杂表达式。由于 Operator 也可以包含多个 Criteria 和 Operator,因此可以通过这种方式构建复杂的表达式树。
有两种运算符
- 并且
- 或者
构建表达式示例
构建条件
1. 简单条件
Criteria exp1 = Criteria.IsNull("Status");
Criteria exp2 = Criteria.IsNotNull("Status");
注意:唯一 SimpleCriteria 是 IsNull 和 IsNotNull。其余都是 ConditionCriteria。
2. 条件
Criteria exp1 = Criteria.Eq("Status", "Choice", "Completed");
Criteria exp2 = Criteria.Neq("Status", "Choice", "Completed");
Criteria exp3 = Criteria.Geq("Price", "Number", "3");
exp1 将生成:
<Eq>
<FieldRef Name='Status' />
<Value Type='Choice'>Completed</Value>
</Eq>
exp2 将生成:
<Neq>
<FieldRef Name='Status' />
<Value Type='Choice'>Completed</Value>
</Neq>
而 exp3 将生成:
<Geq>
<FieldRef Name='Price' />
<Value Type='Number'>3</Value>
</Geq>
构建复杂表达式示例
1. 在运算符下添加条件。
Operator exp = Operator.And(
Criteria.Eq("Status", "Choice", "Completed"),
Criteria.Eq("Priority", "Choice", "High"),
Criteria.Neq("ContactName", "Text", "John")
);
这将构建一个表达式,用于检索所有 Status 是 Completed 且 Priority 是 High,但 ContactName 不是 John 的行。
如您所见,您可以在一个运算符下传递两个以上的条件。Expression 引擎将负责生成正确的 CAML(嵌套运算符)。
注意:运算符必须至少有两个操作数;否则,在生成过程中会抛出异常。
2. 嵌套运算符
您还可以将运算符添加到运算符下以构建复杂的表达式树。
Operator exp = Operator.And(
Criteria.Eq("Status", "Choice", "Completed"),
Operator.Or(
Criteria.Eq("Priority", "Choice", "High"),
Criteria.Neq("ContactName", "Text", "John")
)
);
这将构建一个表达式,用于检索所有 Status 是 Completed,并且 Priority 是 High 或 ContactName 不是 John 的行。
3. 一次添加子表达式
您也可以使用如下构造:
Expression exp = ..
IEnumerable expressions = ...
And and = new And();
and.Add(exp); //add one expression
and.AddRange(expressions); //add multiple expressions at a time
4. 使用 C# 运算符构建表达式
如果已设置好 Criterias 或复杂表达式,您还可以使用标准的 C# 运算符构建它们的复杂表达式。
Criteria exp1 = Criteria.Eq("Status", "Choice", "Completed");
Criteria exp2 = Criteria.Eq("Priority", "Choice", "High");
Criteria exp3 = Criteria.Neq("ContactName", "Text", "John");
Expression exp = Operator.And(
exp1,
Operator.Or(
exp2,
exp3
)
);
//can be rewritten as:
Expression exp = exp1 * (exp2 + exp3);
//or using negate on Eq
Criteria exp4 = Criteria.Eq("ContactName", "Text", "John");
Expression exp = exp1 * (exp2 + !exp4);
- ‘*’ 代表 AND
- ‘+’ 代表 OR
- ‘!’ 代表 Negate
注意:‘*’ 和 ‘+’ 定义在 Expression 级别,因此它们可以用于 Criteria 和 Operator,而 ‘!’ 在 Criteria 级别,因此只能应用于 Criteria,并且只能应用于 Eq、Neq、IsNull 和 IsNotNull 类型!
5. 在条件上添加自定义属性
任何自定义属性也可以在
exp1 = Criteria.Eq("Status", "Number", "2").AddFieldRefAttribute("Explicit", "True");
exp2 = Criteria.Eq("Contact", "Lookup", "2").AddFieldRefAttribute("LookupId", "True");
exp3 = Criteria.Eq("Date", "DateTime", "zz").AddValueAttribute("IncludeTimeValue", "False");
就像 groupby、orderby 一样,这些也可以级联。注意:AddFieldRefAttribute 可用于两种类型的条件,而 AddValueAttribute 只能在 ConditionCriteria 上调用(因为 SimpleCriteria 没有 Value 元素)。
exp2 的输出:
<Eq>
<FieldRef Name='Contact' LookupId='True'
/>
<Value Type='Lookup'>2</Value>
</Eq>
6. 排序
表达式还支持 CAML 排序功能。应用后,标准的 CAML
Expression exp = .... //exp can either be Criteria or Operator
exp.OrderBy("Status", true);
您也可以在表达式中添加多个 OrderBy,因为 OrderBy() 始终返回表达式本身,因此 OrderBy() 调用可以链接在一起并按此顺序呈现。exp = exp.OrderBy("Status", true).OrderBy("Title", false);
注意:OrderBy 可以应用于表达式树中的不同表达式,但始终会添加调用 GetCAMLQuery() 的表达式(根)的表达式。 7. 分组
表达式还支持 CAML 分组功能。应用后,标准的 CAML
Expression exp = .... //exp can either be Criteria or Operator
exp.GroupBy("Status");
您也可以在表达式中添加多个 GroupBy,因为 GroupBy() 始终返回表达式本身,因此 GroupBy() 调用可以链接在一起并按此顺序呈现。exp = exp.GroupBy("Status", true).GroupBy("Title", false);
注意:GroupBy 可以应用于表达式树中的不同表达式,但始终会添加调用 GetCAMLQuery() 的表达式(根)的表达式。 生成结果 CAML 查询
可以通过在 Expression 上调用 GetCAML() 或 GetCAMLQuery() 方法来生成 CAML 查询。由于它定义在 Expression 上,您可以对其调用 Criteria 或 Operator。
Expression exp = ....
exp.GetCAML();
exp.GetCAMLQuery();
GetCAML() 只返回 <Where> 元素的内部部分。不包含 <Where></Where> 的 Where 片段。GetCAMLQuery() 返回一个格式正确的 CAML 查询,其中包含 <Query>、<Where> 元素,并且如果应用了 <OrderBy> 和 <GroupBy>,也会包含它们。
<Query>
<Where>CAML</Where>
<OrderBy>ORDERBY</OrderBy>
<GroupBy>GROUPBY</GroupBy>
</Query>
补充说明
1. Simple 和 Condition Criteria 类的构造函数被设置为内部的,这意味着您只能通过使用基类 Criteria 中定义的静态生成器来实例化它们。这确保了所有条件类型都使用了正确的渲染器。//generates compile time error
Criteria c = new ConditionCriteria("Status", "Choice", "Completed", CriteriaType.Eq);
//correct
Criteria c = Criteria.Eq("Status", "Chocie", "Completed");
2. Criteria 类几乎是不可变的,因为 FieldName、FieldType、CriteriaType 属性只有 getter,只有 Value 属性可以设置,因此表达式也是参数化的。构建后,它可以与不同参数集一起使用。
3. Value 始终作为字符串获取,并将按原样放入结果 CAML 中,因此引擎不会进行任何类型转换或修改字符串,这些需要在用户代码外部完成。
4. 另请注意,FieldType 是作为字符串获取的,因此用户必须确保传入有效的 FieldType。
5. 经 Sharepoint 2007 测试。CAML 在未来版本中可能会有所更改。
结论
所示解决方案非常轻量级,只包含少量类,但在处理 CAML 查询时功能强大,可以节省大量时间。