65.9K
CodeProject 正在变化。 阅读更多。
Home

CAMLBuilder 表达式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (13投票s)

2009年11月15日

CPOL

7分钟阅读

viewsIcon

68994

downloadIcon

1702

使用表达式以编程方式构建 CAML 查询。

使用 CAMLBuilder.Expressions 构建 CAML 查询

本文介绍了一种解决方案,可用于以非常简单的方式以编程方式构造复杂的 Sharepoint CAML 查询。



cd.JPG

解决方案的类图


背景

如果您曾经处理过 Sharepoint 并不得不使用 CAML 查询,您可能会发现有时组合查询是多么痛苦,尤其是在代码中。


参数化固定查询

如果您不想最后连接多个字符串片段,您可以使用流行的工具U2U Caml Query Builderhttp://www.u2u.net)首先设计您的查询,然后对其进行参数化,这样您就可以轻松地将其与任何参数集一起使用。


任意查询

然而,前面的方法不幸地仅适用于固定查询。
如果查询是动态构建的,这意味着构建查询所需的条件集只能在运行时确定,您就无法拥有固定的参数化查询,因为在这种情况下查询本身会发生变化。您仍然可以根据任何条件在运行时连接查询片段(条件),但这正是我们想要避免的。

此外,CAML 语言本身使得构建查询更加困难,因为例如,一个运算符只能有两个操作数,因此您需要根据您拥有的条件数量以不同的方式构建查询。

想象一个场景,您想显示一个已过滤的 Sharepoint 列表,其中过滤条件由用户定义。有时您可能只需要一个过滤器,有时需要多个,或者根本不需要过滤器。
- 如果您有一个过滤器,您不需要 <And> 运算符,只需在查询中有一个条件即可。
- 如果您有两个过滤器,您需要 <And> 运算符并在其下放置两个条件。
- 如果您有多个过滤器,您需要 <And> 运算符并在其下放置条件,但由于运算符只能接受两个操作数,您不能只将所有必需的条件放在 <And> 下,而是需要添加一个内部 <And>,这会引导您构建一个递归。

请参阅以下示例。

CD2.JPG


介绍 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. 在条件上添加自定义属性

任何自定义属性也可以在元素上指定。默认情况下,仅呈现 FieldRef 元素的 Name 属性和 Value 元素的 Type 属性。Sharepoint 有许多这些元素可以接受的其他属性。通过使用 AddXXXAttribute 方法,您可以传递任何自定义属性。
 
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元素将被添加到结果查询中。这在之前的示例中未使用过。这将按升序对 Status 字段进行排序。
 
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元素将被添加到结果查询中。这将按升序对 Status 字段进行排序。
 
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 查询时功能强大,可以节省大量时间。

© . All rights reserved.