Over year ago new feature was announced in Camlex library: lists joins and fields projections. This feature allowed to create lists joins in CAML syntax via C# (I will repeat example from the mentioned post here):
1: var query = new SPQuery();
2:
3: query.Query = Camlex.Query().Where(x => (string)x["CustomerCity"] == "London" &&
4: (string)x["CustomerCityState"] == "UK").ToString();
5:
6: query.Joins = Camlex.Query().Joins()
7: .Left(x => x["CustomerName"].ForeignList("Customers"))
8: .Left(x => x["CityName"].PrimaryList("Customers").ForeignList("CustomerCities"))
9: .Left(x => x["StateName"].PrimaryList("CustomerCities").ForeignList("CustomerCityStates"))
10: .ToString();
11:
12: query.ProjectedFields = Camlex.Query().ProjectedFields()
13: .Field(x => x["CustomerCity"].List("CustomerCities").ShowField("Title"))
14: .Field(x => x["CustomerCityState"].List("CustomerCityStates").ShowField("Title"))
15: .ToString();
16:
17: query.ViewFields = Camlex.Query().ViewFields(x => new[] {x["CustomerCity"],
18: x["CustomerCityState"]});
It will give the following query:
1: <Where>
2: <And>
3: <Eq>
4: <FieldRef Name="CustomerCity" />
5: <Value Type="Text">London</Value>
6: </Eq>
7: <Eq>
8: <FieldRef Name="CustomerCityState" />
9: <Value Type="Text">UK</Value>
10: </Eq>
11: </And>
12: </Where>
joins:
1: <Join Type="LEFT" ListAlias="Customers">
2: <Eq>
3: <FieldRef Name="CustomerName" RefType="Id" />
4: <FieldRef List="Customers" Name="Id" />
5: </Eq>
6: </Join>
7: <Join Type="LEFT" ListAlias="CustomerCities">
8: <Eq>
9: <FieldRef List="Customers" Name="CityName" RefType="Id" />
10: <FieldRef List="CustomerCities" Name="Id" />
11: </Eq>
12: </Join>
13: <Join Type="LEFT" ListAlias="CustomerCityStates">
14: <Eq>
15: <FieldRef List="CustomerCities" Name="StateName" RefType="Id" />
16: <FieldRef List="CustomerCityStates" Name="Id" />
17: </Eq>
18: </Join>
projected:
1: <Field Name="CustomerCity" Type="Lookup" List="CustomerCities" ShowField="Title" />
2: <Field Name="CustomerCityState" Type="Lookup" List="CustomerCityStates" ShowField="Title" />
and view fields:
1: <FieldRef Name="CustomerCity" />
2: <FieldRef Name="CustomerCityState" />
In order to make previous release faster I didn’t include reverse version of this C# to CAML transformation there. I.e. in online service http://camlex-online.org (this service allows to perform transformation in different direction from CAML to C# in order to simplify using Camlex for developers which didn’t use it yet) it was not possible to transform joins and projected fields from CAML to C#. With new release of Camlex 4.1 and Camlex.Client 2.1 it became possible. Now if e.g. the following CAML will be passed there:
1: <Query>
2: <Joins>
3: <Join Type="LEFT" ListAlias="Customers">
4: <Eq>
5: <FieldRef Name="CustomerName" RefType="Id" />
6: <FieldRef List="Customers" Name="Id" />
7: </Eq>
8: </Join>
9: <Join Type="LEFT" ListAlias="CustomerCities">
10: <Eq>
11: <FieldRef List="Customers" Name="CityName" RefType="Id" />
12: <FieldRef List="CustomerCities" Name="Id" />
13: </Eq>
14: </Join>
15: </Joins>
16: </Query>
It will produce the following C# code:
1: Camlex.Query().Joins()
2: .Left(x => x["CustomerName"].ForeignList("Customers"))
3: .Left(x => x["CityName"].PrimaryList("Customers").ForeignList("CustomerCities"))
The same with projected fields:
1:
2: <Query>
3: <ProjectedFields>
4: <Field Name="CustomerCity" Type="Lookup" List="CustomerCities"
5: ShowField="Title" />
6: <Field Name="CustomerCityState" Type="Lookup" List="CustomerCityStates"
7: ShowField="Title" />
8: </ProjectedFields>
9: </Query>
will produce
1: Camlex.Query()
2: .ProjectedFields().Field(x => x["CustomerCity"].List("CustomerCities").ShowField("Title"))
3: .Field(x => x["CustomerCityState"].List("CustomerCityStates").ShowField("Title"))
With new version Camlex and Camlex.Client became complete and fully bidirectional again.