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

Camlex 中对 IN CAML 操作的支持

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2013年11月19日

Ms-PL

2分钟阅读

viewsIcon

15425

描述了 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 组合多个字符串查询,甚至可以将字符串查询与表达式混合,如上所示。 此功能在以前的版本中已添加。

© . All rights reserved.