Expand string CAML queries via lambda expressions with Camlex.Net
Camlex.Net is the free open source library which allows to use lambda
expressions for building CAML queries for SharePoint. Every developer who worked
with CAML know how painful work with string CAML queries can be. You need to
know many specific CAML rules for creating the query, plus you have to rebuild
the whole xml tree when you need to add new condition to the existing query.
Camlex addresses these problems and simplifies creation of the queries using
lambda expressions. You may see some examples e.g. here:
Camlex.NET for Windows SharePoint Services. Until recently Camlex could only
create CAML from expressions, but starting with version 3.2 it supports
expanding of the string queries as well.
In the previous article on the CodeProject (see
Camlex.NET 3.0 and Camlex Online: CAML Reverse Engineering) I announced
release of Camlex.Net 3.0. Starting with this version Camlex works in both
directions: it may translate lambda expressions into strings and it may
translate strings to lambda expressions. We called this feature reverse
engineering. It may have many interesting applications of the Camlex. One of
them is Camlex Online - free online
service which allows developers to refactor their string queries to Camlex
syntax.
Expanding of the string queries using lambda expressions is another
application of the reverse engineering. As many other features the idea came
from the Camlex community
on the project site on the Codeplex.
So what it actually means? Suppose that you have the following string query:
<Where>
<Or>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">Sharepoint</Value>
</Contains>
<Contains>
<FieldRef Name="Description" />
<Value Type="Text">Sharepoint</Value>
</Contains>
</Or>
</Where>
It returns all documents which have "SharePoint" word either in Title or in
Description field. After some point you decide that you need to only fetch
approved documents from the result set of this query. In this example query is simple enough and you can rewrite it on Camlex
completely:
var query = Camlex.Query().Where(x => (((string)x["Title"]).Contains("Sharepoint") ||
((string)x["Description"]).Contains("Sharepoint")) &&
(string)x["Status"] == SPModerationStatusType.Approved.ToString());
It will give the following CAML, which we are looking for:
<Where>
<And>
<Or>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">Sharepoint</Value>
</Contains>
<Contains>
<FieldRef Name="Description" />
<Value Type="Text">Sharepoint</Value>
</Contains>
</Or>
<Eq>
<FieldRef Name="Status" />
<Value Type="Text">Approved</Value>
</Eq>
</And>
</Where>
But in real practice query may be much more complicated. Plus it may come from existing component which you don't want or event can't
modify. So how Camlex may help here? Now it is possible to just pass existing string query
to the Camlex as first parameter and additional condition in lambda expression as second. Camlex will do the rest:
string existingQuery =
"<Where>" +
" <Or>" +
" <Contains>" +
" <FieldRef Name=\"Title\" />" +
" <Value Type=\"Text\">Sharepoint</Value>" +
" </Contains>" +
" <Contains>" +
" <FieldRef Name=\"Description\" />" +
" <Value Type=\"Text\">Sharepoint</Value>" +
" </Contains>" +
" </Or>" +
"</Where>";
var query = Camlex.Query().WhereAll(existingQuery, x => (string)x["Status"] ==
SPModerationStatusType.Approved.ToString()).ToString();
In result you will get the same CAML query which we got above. Camlex needs to know what logical operation should be used for joining string part and lambda
expression part: And or Or. You specify that when select method from IQuery
interface:
WhereAll
or WhereAny
. Similar to the LINQ methods: in
WhereAll
And
operation is used, while in WhereAny Or
.
Using this technique you may also expand existing OrderBy
, GroupBy
, and
ViewFields
parts of the query. Plus you may pass IEnumerable
of expressions for
extending the string queries, which allows you to build them dynamically. More examples can be found
here.
You can download source code and binaries from CodeProject
or from CodePlex.