Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Camlex.NET for Windows SharePoint Services

4.25/5 (3 votes)
27 Jan 2010Ms-PL4 min read 31.7K   220  
Camlex.NET simplifies creating of CAML queries for Windows SharePoint Services by using expression trees

Introduction

Camlex.NET (http://camlex.codeplex.com) is a new tool for Sharepoint developers which allows to use lambda expressions and fluent interfaces in order to write CAML queries. It abstracts developers from syntax of CAML queries and helps them to concentrate on business tasks. With Camlex.NET, developers could think about WHAT they need to do, instead of HOW to do it. It also brings the following advantages for Sharepoint developers:

  • Compile time checking of expressions
  • Natural and intuitive syntax using lambda expressions and fluent interfaces
  • Support for native .NET types (int, strings, bool, DateTime) and operations (==, !=, >, <, etc.)
  • Support for Sharepoint-specific data types
  • Ability to specify non-constant expressions inside filtering conditions (variables, method calls, etc.)
  • Fully customizable resulting query object

In order to start working with Camlex.NET, you should download release package from here and reference Camlex.NET.dll assembly in your project. After that, you can create CAML queries using lambda expressions.

Basic Scenarios

Let's consider some basic scenarios:

Scenario 1. Simple Query

Suppose that you need to select all items which have Status field set to Completed (following is the standard syntax of CAML):

XML
<Where>
  <Eq>
    <FieldRef Name="Status" />
    <Value Type="Text">Completed</Value>
  </Eq>
</Where>

This query can be made with Camlex using the following syntax:

C#
string caml =
    Camlex
        .Query()
    	    .Where(x => (string)x["Status"] == "Completed").ToString();

Scenario 2. Query with “and”/”or” conditions

Suppose that you need to select items which have ProductID = 1000 and IsCompleted set to false or null. Syntax of appropriate standard CAML query follows:

XML
<Where>
  <And>
    <Eq>
      <FieldRef Name="ProductID" />
      <Value Type="Integer">1000</Value>
    </Eq>
    <Or>
      <Eq>
        <FieldRef Name="IsCompleted" />
        <Value Type="Boolean">0</Value>
      </Eq>
      <IsNull>
        <FieldRef Name="IsCompleted" />
      </IsNull>
    </Or>
  </And>
</Where>

With the help of Camlex, it could be converted using the following natural syntax:

C#
var caml =
    Camlex
        .Query()
            .Where(x => (int)x["ProductID"] == 1000 && 
		((bool)x["IsCompleted"] == false || x["IsCompleted"] == null))
                .ToString();

Scenario 3. Query with Non-constant Expressions in lvalue and rvalue

Non-constant expression gives you more control over CAML. Suppose that you need to select items depending on current locale: for English locale, you need to select items which have TitleEng field set to “eng”; for non-English locale, you need to select items which have Title field set to “non-eng”, i.e.:
Query for English locale:

XML
<Where>
  <Eq>
    <FieldRef Name="TitleEng" />
    <Value Type="Text">eng</Value>
  </Eq>
</Where>

Query for non-English locale:

XML
<Where>
  <Eq>
    <FieldRef Name="Title" />
    <Value Type="Text">non-eng</Value>
  </Eq>
</Where>

It is not so hard with Camlex:

C#
bool isEng = true; // or false depending on Thread.CurrentThread.CurrentUICulture

var caml =
    Camlex
        .Query()
            .Where(x => (string)x[isEng ? "TitleEng" : 
		"Title"] == (isEng ? "eng" : "non-eng"))
                .ToString();

Internal Architecture

Generally Camlex – is translator from lambda expression into CAML:

Image 1

It receives expression like:

C#
x => (int)x["ID"] == 1

on input and translates it to a valid CAML query. The exact signature of lambda expressions depends on method call of Camlex public interface. The most important interface in Camlex.NET assembly is IQuery and its implementation – Query class:

C#
public interface IQuery
{
    IQuery Where(Expression<Func<SPItem, bool>> expr);
    IQuery OrderBy(Expression<Func<SPItem, object>> expr);
    IQuery OrderBy(Expression<Func<SPItem, object[]>> expr);
    IQuery GroupBy(Expression<Func<SPItem, object>> expr);
    IQuery GroupBy(Expression<Func<SPItem, object[]>> expr, 
		bool? collapse, int? groupLimit);
    IQuery GroupBy(Expression<Func<SPItem, object>> expr, 
		bool? collapse, int? groupLimit);
    IQuery GroupBy(Expression<Func<SPItem, object>> expr, int? groupLimit);
    IQuery GroupBy(Expression<Func<SPItem, object>> expr, bool? collapse);
    XElement[] ToCaml(bool includeQueryTag);
    string ToString();
    string ToString(bool includeQueryTag);
}

As you can see, most methods return itself – so fluent interface calls are available with Camlex:

C#
var caml =
    Camlex
        .Query()
            .Where(x => x["Status"] != null)
            .GroupBy(x => x["CreatedBy"])
                .ToString();

Also notice that it has ToCaml() method which returns valid XML in array of XElement objects. It means that it can be simply customizable – for example, you can use LINQ to XML or classes from System.Xml.Linq namespace in order to modify resulting query.

Lambda Expressions Syntax

Internally Camlex uses expression trees in order to parse lambda expressions and translate it to CAML. There are 2 types of syntaxes allowed in Camlex (here and below “x” – is a parameter for lambda expression with SPItem data type defined in Microsoft.Sharepoint.dll):

1. Native syntax:

C#
x => (int)x["ID"] == 1

I.e. you write integer rvalue and cast lvalue to int:

2. String based syntax:

C#
x => x["ID"] == (DataTypes.Integer)"1"

Opposite native syntax you write integer value in string representation and cast it to DataTypes.Integer class (helper class defined in Camlex.NET.dll).

Two examples above are equivalent for Camlex. We introduced 2 types of syntaxes in order to be able to write queries with not only native .NET types (int, string, bool, DateTime), but also with Sharepoint data types (see MSDN link). You can easily mix these syntaxes and composite them via logical operations (&&, ||) in the same expression.

The following schema shows how Camlex translates lambda expression with native into CAML query:

Image 2

String based syntax is very similar except Camlex uses rvalue cast to DataTypes.Integer in order to determine type of value and checks that string representation contains valid value for this type.

What happens if Camlex cannot parse lambda expression? As described above, there are only 2 types of syntaxes (and their combination via logical && and || operations) are valid for Camlex. If provided expression has different signature – then CamlexNET.NonSupportedExpressionException will be thrown.

Download Links

You can download Camlex.NET from CodeProject or from CodePlex.

Additional Resources

You can find another scenarios examples on CodePlex or on the Documentation page on CodePlex site of Camlex.NET here or on blogs of the authors:

History

  • 27th January, 2010: Initial version

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)