Camlex 中对 IN CAML 操作的支持





4.00/5 (1投票)
描述了 Camlex 开源库对 SharePoint 开发人员的 IN CAML 操作的支持
引言
Camlex.Net 是一个免费开源项目,供 Sharepoint 开发人员使用,可以简化 CAML 查询的创建(项目站点此处)。 你可以在 Codeproject 此处阅读我之前关于它的文章。 在本文中,我将描述 3.5 版(客户端对象模型版本 - 1.3 版)中添加的新功能:对 IN 操作的支持。
MSDN 文章对 IN 操作的描述如下:
“指定列表项中由 FieldRef 元素指定的字段的值是否等于由 Values 元素指定的值之一。”
例如,如果我们需要获取所有 Count 字段在 0..9 范围内的列表项,我们可以使用以下查询:
<Where>
<In>
<FieldRef Name="Count" />
<Values>
<Value Type="Integer">0</Value>
<Value Type="Integer">1</Value>
<Value Type="Integer">2</Value>
<Value Type="Integer">3</Value>
<Value Type="Integer">4</Value>
<Value Type="Integer">5</Value>
<Value Type="Integer">6</Value>
<Value Type="Integer">7</Value>
<Value Type="Integer">8</Value>
<Value Type="Integer">9</Value>
</Values>
</In>
</Where>
可以使用 Or 组合多个 Eq 操作来获得相同的结果。 使用 Camlex,可以使用单行代码很容易地做到这一点(为了更好的阅读,我将其分为 3 行)
string caml = Camlex.Query().WhereAny(
Enumerable.Range(0, 9).Select<int, Expression<Func<SPListItem, bool>>>(
i => x => (int) x["Count"] == i)).ToString();
让我们看看上面代码生成的 CAML
<Where>
<Or>
<Or>
<Or>
<Or>
<Or>
<Or>
<Or>
<Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">0</Value>
</Eq>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">1</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">2</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">3</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">4</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">5</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">6</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">7</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">8</Value>
</Eq>
</Or>
</Where>
与第一个示例相比,它看起来不是很美观。 如果你不在意,仍然可以使用 OR 语法。 但是,现在可以编写更简单的表达式来生成 IN 语法
string caml = Camlex.Query().Where(x => Enumerable.Range(0, 9).Contains((int)x["Count"])).ToString();
它将生成我们已经看到的 CAML
<Where>
<In>
<FieldRef Name="Count" />
<Values>
<Value Type="Integer">0</Value>
<Value Type="Integer">1</Value>
<Value Type="Integer">2</Value>
<Value Type="Integer">3</Value>
<Value Type="Integer">4</Value>
<Value Type="Integer">5</Value>
<Value Type="Integer">6</Value>
<Value Type="Integer">7</Value>
<Value Type="Integer">8</Value>
</Values>
</In>
</Where>
对于那些使用过 NHibernate 或 Linq2Sql 的人来说,这种语法并不新鲜:这些 ORM 框架使用相同的语法来生成带有 IN 运算符的 SQL 查询。 我故意展示了一个使用动态填充数组的示例 (Enumerable.Range(0, 9)):代码支持任何生成 IEnumerable 的表达式
var caml = Camlex.Query().Where(x => getArray().Contains((int)x["Count"])).ToString();
...
List<int> getArray()
{
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
}
return list;
}
(你看到最后一个示例(返回 List<int> 的函数)与前一个示例(使用 IEnumerable)之间的区别了吗? 类 List<T> 有自己的 Contains 方法,而对于第一个示例中的 IEnumerable<int>,使用了 Linq Contains 扩展方法。 正如你所看到的,Camlex 可以与两者一起使用。 请注意,如果你使用 Linq,则应将“using System.Linq;”添加到你的文件中)。
即,基本语法如下:
var caml = Camlex.Query().Where(x => enumerable.Contains((Type)x["FieldTitle"])).ToString();
当然,你可以编写带有常量的数组
string c = Camlex.Query().Where(x => new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
.Contains((int) x["Count"])).ToString();
它也适用于 Value 元素支持的任何类型
string c = Camlex.Query().Where(x => new[]
{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
.Contains((string) x["Title"])).ToString();
它将产生以下结果
<Where>
<In>
<FieldRef Name="Title" />
<Values>
<Value Type="Text">zero</Value>
<Value Type="Text">one</Value>
<Value Type="Text">two</Value>
<Value Type="Text">three</Value>
<Value Type="Text">four</Value>
<Value Type="Text">five</Value>
<Value Type="Text">six</Value>
<Value Type="Text">seven</Value>
<Value Type="Text">eight</Value>
<Value Type="Text">nine</Value>
</Values>
</In>
</Where>
现在它在 Value 元素中使用 Text 类型。
这只是故事的一半。 如果你关注 Camlex,你可能知道从 3.0 版本开始,它变成了双向的(我在这里写过:Camlex.NET 变成双向的并上线。发布了 3.0 版本)。 因此,所有转换都添加了 2 个方向:从表达式到 CAML,以及从 CAML 到表达式
var xml =
"<Query>" +
" <Where>" +
" <In>" +
" <FieldRef Name=\"Title\" />" +
" <Values>" +
" <Value Type=\"Text\">zero</Value>" +
" <Value Type=\"Text\">one</Value>" +
" <Value Type=\"Text\">two</Value>" +
" <Value Type=\"Text\">three</Value>" +
" <Value Type=\"Text\">four</Value>" +
" <Value Type=\"Text\">five</Value>" +
" <Value Type=\"Text\">six</Value>" +
" <Value Type=\"Text\">seven</Value>" +
" <Value Type=\"Text\">eight</Value>" +
" <Value Type=\"Text\">nine</Value>" +
" </Values>" +
" </In>" +
" </Where>" +
"</Query>";
var expr = Camlex.QueryFromString(xml).ToExpression();
该功能的应用
1. 在 http://camlex-online.org/ 上,将下面显示的 xml 添加到 textarea 中,然后单击“转换为 C#”。 它会向你展示 Camlex 将如何生成此查询
Camlex.Query().Where(x => new[] {
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }
.Contains((string)x["Title"]))
2. 可以向存储为 xml 的现有 IN 查询添加更多条件,或者向现有查询添加 IN 查询
var xml =
"<Query>" +
" <Where>" +
" <In>" +
" <FieldRef Name=\"Title\" />" +
" <Values>" +
" <Value Type=\"Text\">one</Value>" +
" <Value Type=\"Text\">two</Value>" +
" </Values>" +
" </In>" +
" </Where>" +
"</Query>";
string caml = Camlex.Query().WhereAll(xml, x => (int)x["Count"] == 1).ToString();
将会生成
<Where>
<And>
<Eq>
<FieldRef Name="Count" />
<Value Type="Integer">1</Value>
</Eq>
<In>
<FieldRef Name="Title" />
<Values>
<Value Type="Text">one</Value>
<Value Type="Text">two</Value>
</Values>
</In>
</And>
</Where>
即,Camlex 可以使用 Or 和 And 组合多个字符串查询,甚至可以将字符串查询与表达式混合,如上所示。 此功能在以前的版本中已添加。