Vous êtes sur la page 1sur 20

Join et ProjectedFields Ralisation de jointures en CAML

par Sbastien Sougnez (Home page) (Blog)


Date de publication : 18 dcembre 2009 Dernire mise jour :

Une volution majeure de SharePoint 2010 par rapport son prdcesseur est l'introduction des jointures dans les requtes CAML. Effectivement, si vous avez dj utilis le CAML sous SharePoint 2007, vous vous serez certainement rendu compte qu'il tait impossible d'excuter des jointures grce aux requtes CAML. Cela limitait considrablement l'utilisation des requtes faisant intervenir plusieurs tables. Avec SharePoint 2010, il est maintenant possible d'utiliser des joins et des projected fields pour raliser des jointures entre tables.

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

I - Jointures simples.................................................................................................................................................... 3 II - Jointures complexes............................................................................................................................................ 12

-2Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

I - Jointures simples
Une volution majeure de SharePoint 2010 par rapport son prdcesseur est l'introduction des jointures dans les requtes CAML. Effectivement, si vous avez dj utilis le CAML sous SharePoint 2007, vous vous serez certainement rendu compte qu'il tait impossible d'excuter des jointures grce aux requtes CAML. Cela limitait considrablement l'utilisation des requtes faisant intervenir plusieurs tables. Avec SharePoint 2010, il est maintenant possible d'utiliser des joins et des projected fields pour raliser des jointures entre tables. Nous allons dvelopper une Visual Web Part qui se chargera d'excuter diffrentes requtes CAML et d'afficher le rsultat pour voir toute la puissance des jointures (pour ceux qui ne connaissent pas ce concept en SQL). Commencez par crer un nouveau projet de type Visual Web Part que vous nommerez DVP.VisualWebParts.JoinProjectedFields :

-3Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

-4Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

tant donn que cette solution dploiera des fichiers dans un des rpertoires systme de SharePoint, laissez "Deploy as farm solution" coche. Dans l'arborescence de votre projet, reprez VisualWebPart1 et supprimez-la. Cliquez ensuite avec le bouton droit sur votre projet et choisissez Add > New Item et choisissez Visual Web Part. Nommezla "JoinProjectedFields" :

-5Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

-6Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Double-cliquez maintenant sur le fichier Elements.xml pour modifier le nom du groupe dans lequel la WebPart ira s'insrer. Remplacez donc Custom par Developpez :
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/" > <Module Name="JoinProjectedFields" List="113" Url="_catalogs/wp"> <File Path="JoinProjectedFields \JoinProjectedFields.webpart" Url="JoinProjectedFields.webpart" Type="GhostableInLibrary" > <Property Name="Group" Value="Developpez" /> </File> </Module> </Elements>

Ouvrez maintenant le fichier JoinProjectedFields.webpart et modifiez la proprit Title sur "Join et Projected Fields" et la proprit Description sur "Utilisation des jointures en CAML" :
<?xml version="1.0" encoding="utf-8"?> <webParts> <webPart xmlns="http://schemas.microsoft.com/WebPart/v3"> <metaData>

<type name="DVP.VisualWebParts.JoinProjectedFields.JoinProjectedFields.JoinProjectedFields, $SharePoint.Project. $" /> <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage> </metaData> <data> <properties> <property name="Title" type="string">Join et Projected Fields</property> <property name="Description" type="string">Utilisation des jointures en CAML</property> </properties> </data> </webPart> </webParts>

Avant d'attaquer le code du projet, nous allons dcrire l'architecture du site que nous allons utiliser pour dmontrer l'utilisation des jointures. Nous allons disposer de trois listes. La premire se nommera Pays et contiendra les valeurs suivantes :

Nous avons ensuite la liste Villes :

-7Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Le champ Pays est de type Lookup et pointe sur la liste des pays vue prcdemment. Cela est une condition pour effectuer des jointures entre deux listes. Effectivement, le champ servant effectuer la jointure devra absolument tre de type Lookup, vous verrez ensuite pourquoi. Enfin, nous avons la liste Monuments :

Le champ Ville de cette liste est galement un champ de type Lookup pointant vers la liste des villes. Le but de cette architecture est assez simple. Nous avons la liste Monuments qui va nous permettre de stocker des monuments clbres tels que le Colise, la tour Eiffel... Chacun de ces monuments se trouve dans une ville qui sera contenue dans la liste Villes. Et chacune de ces villes se trouvera dans un pays contenu dans la liste Pays. Nous n'exigeons pas que les Lookup contiennent des valeurs pour dmontrer la diffrence entre les jointures de type INNER et LEFT. Vous avez certainement remarqu que le monument Projet n'a pas de ville. Effectivement, ce monument est un projet et la ville de ce monument n'a pas encore t choisie, nous n'avons donc slectionn aucune ville. Pour ceux qui ne savent pas ce que sont les jointures, nous allons expliquer cela tout de suite. Les personnes savant quoi servent INNER JOIN, LEFT JOIN... en SQL peuvent passer ce passage car il ne leur apprendra rien. Le problme induit par cette architecture est assez simple. Imaginez que vous vouliez rcuprer tous les monuments contenus dans la liste mais galement les informations sur la ville et le pays de ce monument. La technique en SharePoint 2007 serait de faire une premire requte rcuprant tous les monuments, une deuxime requte rcuprant les villes et une troisime requte rcuprant les pays. Ensuite, selon un systme de stockage en mmoire base de classes, vous vous seriez arrangs pour que les monuments soient lis aux villes et les villes aux pays. Cela aurait bien fonctionn mais n'aurait pas t trs performant. Dans SharePoint 2010, la technique utilise sera les jointures. Effectivement, il va tre possible de raliser les 3 requtes en une seule. Pour cela, la requte devra dire : Rcuprer tous les monuments en liant les villes de ces monuments et les pays de ces villes.
-8Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

La requte renverrait donc toutes les informations d'un coup. Bien entendu, la jointure devra tre effectue sur une certaine valeur. En franais, cela donnerait : Rcuprer le monument X ainsi que la ville du monument X. Donc, si nous nous basons sur notre architecture actuelle et que nous voulions rcuprer la Tour Eiffel, nous dirions : Rcuprer le monument pour lequel le titre vaut Tour Eiffel et rcuprer la ville dont le titre vaut la valeur du champ Ville du monument (donc Paris). Sous SharePoint 2007, il aurait t impossible de traduire cette requte en CAML. C'est maintenant faisable en SharePoint 2010. Avant de passer l'exemple, il faut savoir une dernire chose. En CAML, il est possible d'effectuer des jointures de type INNER ou de type LEFT. La diffrence entre ces deux types de jointures est trs importante. Nous verrons cela lors de l'explication de notre exemple. Revenez donc dans votre classe et ajoutez la directive suivante :
using Microsoft.SharePoint;

Dclarez ensuite la fonction suivante :


private void AfficherMonumentEtVille(string type) { }

Le but de cette fonction sera d'afficher tous les monuments ainsi que les informations sur leur ville et leur pays. Le paramtre type va permettre de dfinir si la jointure sera de type LEFT ou INNER et nous permettra de comprendre la diffrence. La premire chose faire dans cette fonction est de rcuprer une rfrence la liste et de crer un objet SPQuery pour raliser la requte :
SPList list = SPContext.Current.Web.Lists["Monuments"]; SPQuery query = new SPQuery();

Nous allons nous baser sur la liste Monuments car ce sont les informations des monuments et les informations lies ce monument que nous voulons rcuprer. Nous allons maintenant dfinir la proprit Joins de la requte. C'est dans cette proprit que nous allons dfinir le format de la jointure. Nous allons directement afficher le code du Joins et nous l'expliquerons aprs :
query.Joins = string.Format("<Join Type='{0}' ListAlias='VillesList'>" + "<Eq>" + "<FieldRef Name='Ville' RefType='Id' />" + "<FieldRef List='VillesList' Name='ID' />" + "</Eq>" + "</Join>", type);

Comme nous venons de le dire, la proprit Joins va permettre de contenir du code CAML indiquant comment la ou les jointures seront effectues. Ici, pour commencer, nous n'allons effectuer qu'une seule jointure. En gros, nous allons joindre la table Monuments la table Villes grce au champ Ville de la table monument. Ainsi, nous rcuprerons les informations de chaque monument ainsi que les informations sur la ville dans laquelle se trouvent ces monuments. Une jointure est donc introduite grce l'lment Join. Cet lment attend deux paramtres. Le premier se nomme Type et permet de dfinir le type de la jointure. La valeur de cet attribut peut soit tre LEFT soit INNER. Nous verrons plus tard ce que cela reprsente. L'attribut ListAlias quant lui va permettre de donner un autre nom la table que nous joignons. Ici, la premire table est bien entendu la table sur laquelle la requte sera excute, savoir Monuments. Nous allons ensuite joindre la table Villes et nous lui donnerons comme alias VillesList.

-9Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Nous devons ensuite tester l'galit. Pour cela, nous utiliserons donc l'lment Eq pour introduire la comparaison. Cet lment doit alors contenir deux lments FieldRef qui serviront chacun quelque chose de bien prcis. Le premier FieldRef va permettre d'indiquer quel champ dans la premire liste (Monuments) contiendra la rfrence la deuxime liste (Villes). Ce champ doit obligatoirement tre un Lookup. Ici, nous indiquons donc que le nom du champ est Ville (tant le nom du Lookup de la liste Monuments). Nous ajoutons ensuite RefType='Id' pour indiquer que la comparaison sera faite sur l'ID que ce champ contient. Effectivement, un champ de type Lookup contient une rfrence vers l'lment cible sous forme de "ID;#Valeur". RefType='Id' permet donc de faire la comparaison avec l'ID. Le deuxime lment FieldRef va nous permettre d'indiquer le champ dans la deuxime liste auquel sera compare la valeur du Lookup. tant donn que nous extrayons l'ID du champ Lookup, nous ferons bien sr rfrence au champ ID de la liste Villes. Nous faisons donc passer l'alias de la liste Villes comme valeur de l'attribut List qui permet de spcifier quelle liste appartient le champ auquel on fait rfrence. Nous indiquons enfin que nous rcuprons le champ ID de cette liste pour effectuer la comparaison. Et c'est tout, la jointure est effectue. Mais il reste une question se poser... aucun moment nous n'avons dfini que c'est avec la liste nomme Villes que nous ferons la jointure. Nous avons bien donn un alias la deuxime liste ( savoir VillesList), mais aucun moment nous n'avons indiqu clairement que la jointure sera effectue avec la liste Villes. En fait, cela est dit implicitement. Effectivement, quand nous spcifions que la comparaison sera effectue grce au Lookup field Ville, la requte va directement regarder vers quelle liste ce champ pointe. Il va voir que c'est vers la liste Villes et c'est donc avec cette liste que la jointure sera effectue. Nous allons maintenant devoir utiliser des projected fields. En fait, quand vous allez effectuer la jointure, tous les champs des deux tables seront prsents, mais il faudra bien trouver une manire de savoir les afficher. Par exemple, actuellement, notre jointure lie la table Monuments la table Villes, mais comment faire pour rcuprer le champ Title d'une de ces deux tables. Effectivement, ce champ existant dans les deux tables, il pourrait y avoir un risque de confusion. C'est donc l qu'interviennent les projected fields. Par dfaut, seuls les champs de la premire liste seront rcuprs, il nous faudra ensuite projeter les champs de la deuxime liste pour pouvoir les rcuprer. Tapez donc ce code la suite du prcdent :
query.ProjectedFields = "<Field Name='VilleTitle' Type='Lookup' List='VillesList' ShowField='Title' / >" + "<Field Name='VilleSuperficie' Type='Lookup' List='VillesList' ShowField='Superficie' />";

Nous allons ici dfinir quel champ dans la liste lie nous allons rcuprer. La syntaxe est trs simple. Chaque champ projet sera identifi grce un lment Field. L'attribut Name permet de dfinir le nom qu'il aura au final dans l'objet model. Ici, nous ne pouvons pas mettre Title tant donn que ce nom de champ est dj utilis pour le Title du monument. Nous devons ensuite dfinir que le type de ce champ est un Lookup. Ensuite, nous avons l'attribut List qui permet de dfinir de quelle liste nous rcuprons le champ. Il faut ici faire passer l'alias de cette liste, nous faisons donc passer celui de la liste Villes. Ensuite, l'attribut ShowField permet de faire passer le nom du champ rcuprer dans la liste identifie par l'attribut List. Le premier lment va donc rcuprer le champ Title de la liste Villes et le placer dans un champ nomm VilleTitle. Le deuxime lment va rcuprer le champ Superficie de la liste Villes et le placer dans le champ nomm VilleSuperficie. Nous dfinissons ensuite l'lment ViewFields qui va permettre de dfinir quels champs seront renvoys par la requte CAML :
query.ViewFields = "<FieldRef "<FieldRef "<FieldRef @"<FieldRef Name='Title' />" + Name='Entrepreneur' />" + Name='VilleTitle'/>" + Name='VilleSuperficie'/>";

Nous rcuprons ici le champ nomm Title, le champ Entrepreneur, le champ VilleTitle et le champ VilleSuperficie. Vient ensuite le code permettant d'afficher tout cela dans la WebPart :
SPListItemCollection items = list.GetItems(query); string villeSuperficie; string villeTitle; - 10 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Controls.Add(new LiteralControl(string.Format("<h1>Monuments avec leur ville (<u>{0}</u>)</h1><br />", type))); foreach (SPListItem it in items) { villeTitle = (it["VilleTitle"] != null) ? it["VilleTitle"].ToString().Substring(it["VilleTitle"].ToString().IndexOf(";#") + 2) : "[Non dfini]"; if (it["VilleSuperficie"] != null) { villeSuperficie = it["VilleSuperficie"].ToString().Substring(it["VilleSuperficie"].ToString().IndexOf(";#") + 2); villeSuperficie = villeSuperficie.Substring(0, villeSuperficie.IndexOf(".")); } else villeSuperficie = "[Non dfini]"; Controls.Add(new LiteralControl(string.Format("<b>{0}</b> a t construit par <b>{1}</ b> dans la ville de <b>{2}</b> ayant une superficie de <b>{3}</b> km<br />", it["Title"], it["Entrepreneur"], villeTitle, villeSuperficie))); }

Ce code n'est pas trs compliqu. Nous utilisons l'objet query avec la mthode GetItems de la liste pour rcuprer les lments correspondant la requte dfinie. Nous devons ensuite vrifier si le champ VilleSuperficie existe, car cela n'est pas certain quand nous faisons une requte du type LEFT. Nous allons voir a trs prochainement. Nous rcuprons ensuite le champ en faisant des oprations dessus, car tant un champ du type Lookup, il renvoie ID;#Valeur, nous devons donc uniquement rcuprer la partie Valeur, nous faisons donc un Substring depuis la position de ;# + 2. Placez-vous maintenant dans la fonction Page_Load et appelez cette fonction de cette manire :
AfficherMonumentEtVille("LEFT"); AfficherMonumentEtVille("INNER");

Nous appelons donc la mme fonction, mais le premier appel ralisera une requte de type LEFT alors que le deuxime appel ralisera une requte de type INNER. Voici le rsultat renvoy par ces deux requtes :

- 11 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

La diffrence entre les deux requtes est que celle de type LEFT va renvoyer un lment de plus que celle du type INNER. En fait, la raison est assez simple et va concerner l'lment Projet. Effectivement, celui-ci existe bien dans la liste Monuments mais son champ Ville n'a pas t dfini. Il n'y a donc aucune concordance entre la valeur de ce champ et un lment dans la liste des villes. Dans ce cas, si aucune correspondance n'est trouve entre les listes, une jointure de type INNER ne renverra carrment pas l'lment. Par contre, une jointure du type LEFT renverra quand mme l'lment avec les proprits dfinies dans la liste Monuments, mais tant donn qu'aucune correspondance ne sera trouve dans la liste Villes, elle ne renverra pas les champs de cette liste. C'est en fait pour cela que nous avons test si le champ VilleSuperficie existe bien dans le rsultat avant d'effectuer des oprations dessus.

II - Jointures complexes
Passons maintenant la deuxime requte. Celle-ci va effectuer une requte relativement similaire sauf qu'elle joindra galement la liste Pays la requte pour rcuprer les informations du pays dans lequel se trouve la ville du monument. Tapez donc le squelette de la fonction comme ceci :
private void AfficherMonumentEtVilleEtPays(string type) { }

Nous ferons encore passer le type de la jointure en paramtre pour bien afficher la diffrence de type. Comme prcdemment, nous commenons le code de la fonction par la rcupration de la liste et la cration d'un nouvel objet SPQuery :
SPList list = SPContext.Current.Web.Lists["Monuments"]; SPQuery query = new SPQuery();

Tapez donc ensuite le code suivant pour effectuer la jointure des 3 tables :

- 12 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

query.Joins = string.Format("<Join Type='{0}' ListAlias='VillesList'>" + "<Eq>" + "<FieldRef Name='Ville' RefType='Id' />" + "<FieldRef List='VillesList' Name='ID' />" + "</Eq>" + "</Join>" + "<Join Type='{0}' ListAlias='PaysList'>" + "<Eq>" + "<FieldRef List='VillesList' Name='Pays' RefType='Id' />" + "<FieldRef List='PaysList' Name='ID' />" + "</Eq>" + "</Join>", type);

Nous effectuons ici deux jointures. La premire de ces deux jointures est la mme que celle que nous avons ralise dans la fonction prcdente (relisez donc l'explication de celle-ci si vous ne comprenez pas). Une fois la liste Villes jointe la liste Monuments, nous allons devoir joindre la liste Pays la liste Villes sur la base du champ Pays de la liste Villes. Nous effectuons donc une jointure du type pass en paramtre. Nous appelons ensuite la liste Pays (dclare implicitement par le Lookup) PaysList. Le premier FieldRef permet donc de dfinir une rfrence vers le Lookup permettant de faire la jointure. Ici, il s'agit du champ Pays dans la liste Villes. tant donn que cette liste n'est pas celle sur laquelle la requte sera excute, nous devons utiliser l'attribut List de FieldRef pour indiquer l'alias de la liste contenant le Lookup, donc VillesList. Le deuxime FieldRef indique simplement que la comparaison se fera avec le champ ID de la liste des pays. Passons maintenant au projection des champs :
query.ProjectedFields = "<Field Name='VilleTitle' Type='Lookup' List='VillesList' ShowField='Title' / >" + "<Field Name='VilleSuperficie' Type='Lookup' List='VillesList' ShowField='Superficie' />" + "<Field Name='PaysTitle' Type='Lookup' List='PaysList' ShowField='Title' />" + "<Field Name='PaysSuperficie' Type='Lookup' List='PaysList' ShowField='Superficie' />" + "<Field Name='Habitants' Type='Lookup' List='PaysList' ShowField='Nombre_x0020_d_x0027_habitant' />";

Nous projetons donc simplement les champs de la liste Villes et de la liste Pays en leur donnant des noms explicites. Nous dfinissons ensuite le ViewFields de la requte pour dfinir quel champ la liste devra retourner :
query.ViewFields = "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef Name='Title' />" + Name='Entrepreneur' />" + Name='VilleTitle' />" + Name='VilleSuperficie' />" + Name='PaysTitle' />" + Name='PaysSuperficie' />" + Name='Habitants' />";

Enfin, comme dans la fonction prcdente, nous bouclons sur les lments renvoys par la requte de nous en affichons le contenu :
SPListItemCollection items = list.GetItems(query); string string string string string villeSuperficie; villeTitle; paysSuperficie; paysTitle; paysHabitant;

- 13 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog) Controls.Add(new LiteralControl(string.Format("<h1>Monuments avec leur ville et leur pays (<u>{0}</ u>)</h1><br />", type))); foreach (SPListItem it in items) { paysTitle = (it["PaysTitle"] != null) ? it["PaysTitle"].ToString().Substring(it["PaysTitle"].ToString().IndexOf(";#") + 2) : "[Non dfini]"; villeTitle = (it["VilleTitle"] != null) ? it["VilleTitle"].ToString().Substring(it["VilleTitle"].ToString().IndexOf(";#") + 2) : "[Non dfini]"; if (it["VilleSuperficie"] != null) { villeSuperficie = it["VilleSuperficie"].ToString().Substring(it["VilleSuperficie"].ToString().IndexOf(";#") + 2); villeSuperficie = villeSuperficie.Substring(0, villeSuperficie.IndexOf(".")); } else villeSuperficie = "[Non dfini]"; if (it["PaysSuperficie"] != null) { paysSuperficie = it["PaysSuperficie"].ToString().Substring(it["PaysSuperficie"].ToString().IndexOf(";#") + 2); paysSuperficie = paysSuperficie.Substring(0, paysSuperficie.IndexOf(".")); } else paysSuperficie = "[Non dfini]"; if (it["Habitants"] != null) { paysHabitant = it["Habitants"].ToString().Substring(it["Habitants"].ToString().IndexOf(";#") + 2); paysHabitant = paysHabitant.Substring(0, paysHabitant.IndexOf(".")); } else paysHabitant = "[Non dfini]"; Controls.Add(new LiteralControl(string.Format(@"<b>{0}</b> a t construit par <b>{1}</b> dans la ville de <b>{2}</b> ayant une superficie de <b>{3}</b> km en <b>{4}</b>.<br /> Ce pays compte <b>{5}</b> habitants pour une superficie de <b>{6}</b> km.<br /><br />", it["Title"], it["Entrepreneur"], villeTitle, villeSuperficie, paysTitle, paysHabitant, paysSuperficie))); }

Dans votre fonction Page_Load, vous appellerez cette mthode de cette manire :
AfficherMonumentEtVilleEtPays("LEFT"); AfficherMonumentEtVilleEtPays("INNER");

Ce qui aura pour effet d'afficher :

- 14 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Toutes les informations ont bien t rcupres et affiches. Et comme tout l'heure, vous pouvez remarquer que la requte de type LEFT renvoie un lment en plus, mais que la valeur de ces champs n'a pas t initialise. Du moins pour les champs contenus dans les tables n'ayant pas pu tre jointes. Passons maintenant une autre requte qui va permettre d'afficher toutes les informations du monument nomm Tour Eiffel. Tapez d'abord le squelette de la fonction :
private void AfficherTourEiffel() { ]

Pour ce qui est de la jointure, des champs projets et des champs rcuprs, nous utiliserons les mmes dfinitions que pour la fonction prcdente :

- 15 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

SPList list = SPContext.Current.Web.Lists["Monuments"]; SPQuery query = new SPQuery(); query.Joins = "<Join Type='LEFT' ListAlias='VillesList'>" + "<Eq>" + "<FieldRef Name='Ville' RefType='Id' />" + "<FieldRef List='VillesList' Name='ID' />" + "</Eq>" + "</Join>" + "<Join Type='LEFT' ListAlias='PaysList'>" + "<Eq>" + "<FieldRef List='VillesList' Name='Pays' RefType='Id' />" + "<FieldRef List='PaysList' Name='ID' />" + "</Eq>" + "</Join>"; query.ProjectedFields = "<Field Name='VilleTitle' Type='Lookup' List='VillesList' ShowField='Title' / >" + "<Field Name='VilleSuperficie' Type='Lookup' List='VillesList' ShowField='Superficie' />" + "<Field Name='PaysTitle' Type='Lookup' List='PaysList' ShowField='Title' />" + "<Field Name='PaysSuperficie' Type='Lookup' List='PaysList' ShowField='Superficie' />" + "<Field Name='Habitants' Type='Lookup' List='PaysList' ShowField='Nombre_x0020_d_x0027_habitant' />"; query.ViewFields = "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef Name='Title' />" + Name='Entrepreneur' />" + Name='VilleTitle' />" + Name='VilleSuperficie' />" + Name='PaysTitle' />" + Name='PaysSuperficie' />" + Name='Habitants' />";

Si vous ne comprenez pas ces lignes de code, nous vous conseillons de relire les paragraphes prcdents. La nouveaut se situe dans la suite du code :
query.Query = "<Where>" + "<Eq>" + "<FieldRef Name='Title' />" + "<Value Type='Text'>Tour Eiffel</Value>" + "</Eq>" + "</Where>";

Ici, nous dfinissons le cur de la requte qui va permettre de poser des conditions la rcupration des lments. Nous introduisons donc la condition avec l'lment Where. Le but de cette requte est de rcuprer les lments pour lesquels le champ Title (de la liste Monument) vaudra Tour Eiffel. Nous utilisons donc trs simplement les lments Eq, FieldRef et Value pour effectuer la condition. Pour ce qui est du nom du champ, nous passons btement Title pour indiquer qu'il s'agit du titre de l'lment de la liste de base (Monuments). La suite du code est la suivante :
SPListItem it = list.GetItems(query)[0]; string string string string string villeSuperficie; villeTitle; paysSuperficie; paysTitle; paysHabitant;

Controls.Add(new LiteralControl("<h1>Tour Eiffel</h1><br />")); paysTitle = it["PaysTitle"].ToString().Substring(it["PaysTitle"].ToString().IndexOf(";#") + 2); villeTitle = it["VilleTitle"].ToString().Substring(it["VilleTitle"].ToString().IndexOf(";#") + 2);

- 16 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog) villeSuperficie = it["VilleSuperficie"].ToString().Substring(it["VilleSuperficie"].ToString().IndexOf(";#") + 2); villeSuperficie = villeSuperficie.Substring(0, villeSuperficie.IndexOf(".")); paysSuperficie = it["PaysSuperficie"].ToString().Substring(it["PaysSuperficie"].ToString().IndexOf(";#") + 2); paysSuperficie = paysSuperficie.Substring(0, paysSuperficie.IndexOf(".")); paysHabitant = it["Habitants"].ToString().Substring(it["Habitants"].ToString().IndexOf(";#") + 2); paysHabitant = paysHabitant.Substring(0, paysHabitant.IndexOf(".")); Controls.Add(new LiteralControl(string.Format(@"<b>{0}</b> a t construit par <b>{1}</b> dans la ville de <b>{2}</b> ayant une superficie de <b>{3}</b> km en <b>{4}</b>.<br /> Ce pays compte <b>{5}</b> habitants pour une superficie de <b>{6}</b> km.<br /><br />", it["Title"],

Nous trichons un peu dans ce code. Effectivement, nous savons que l'lment existe, nous rcuprons donc directement l'lment l'index 0. Nous savons galement que les champs Ville et Pays sont initialiss, nous ne testons donc pas leur existence. Appelez maintenant cette fonction depuis Page_Load de cette manire :
AfficherTourEiffel();

L'excution de cette requte produira le rsultat suivant :

L'lment Tour Eiffel ainsi que les valeurs de tous ces champs ont bien t rcuprs. Passons maintenant la dernire fonction qui va nous permettre d'effectuer des conditions sur les champs des listes jointes. Voici donc le code entier de cette fonction :
private void AfficherMonumentsSelonSuperficie(int superficiePays, int superficieVille) { SPList list = SPContext.Current.Web.Lists["Monuments"]; SPQuery query = new SPQuery(); query.Joins = "<Join Type='LEFT' ListAlias='VillesList'>" + "<Eq>" + "<FieldRef Name='Ville' RefType='Id' />" + "<FieldRef List='VillesList' Name='ID' />" + "</Eq>" + "</Join>" + "<Join Type='LEFT' ListAlias='PaysList'>" + "<Eq>" + "<FieldRef List='VillesList' Name='Pays' RefType='Id' />" + "<FieldRef List='PaysList' Name='ID' />" + "</Eq>" + "</Join>";

- 17 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

query.ProjectedFields = "<Field Name='VilleTitle' Type='Lookup' List='VillesList' ShowField='Title' / >" + "<Field Name='VilleSuperficie' Type='Lookup' List='VillesList' ShowField='Superficie' />" + "<Field Name='PaysTitle' Type='Lookup' List='PaysList' ShowField='Title' / >" + "<Field Name='PaysSuperficie' Type='Lookup' List='PaysList' ShowField='Superficie' />" + "<Field Name='Habitants' Type='Lookup' List='PaysList' ShowField='Nombre_x0020_d_x0027_habitant' />"; query.ViewFields = "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef "<FieldRef Name='Title' />" + Name='Entrepreneur' />" + Name='VilleTitle' />" + Name='VilleSuperficie' />" + Name='PaysTitle' />" + Name='PaysSuperficie' />" + Name='Habitants' />";

query.Query = string.Format("<Where>" + "<And>" + "<Geq>" + "<FieldRef Name='PaysSuperficie' />" + "<Value Type='Number'>{0}</Value>" + "</Geq>" + "<Geq>" + "<FieldRef Name='VilleSuperficie' />" + "<Value Type='Number'>{1}</Value>" + "</Geq>" + "</And>" + "</Where>", superficiePays, superficieVille); SPListItemCollection items = list.GetItems(query); string string string string string villeSuperficie; villeTitle; paysSuperficie; paysTitle; paysHabitant;

Controls.Add(new LiteralControl(string.Format("<h1>Monuments selon la superficie ( Pays : {0}, Ville : {1} )</h1><br / >", superficiePays, superficieVille))); foreach (SPListItem it in items) { paysTitle = (it["PaysTitle"] != null) ? it["PaysTitle"].ToString().Substring(it["PaysTitle"].ToString().IndexOf(";#") + 2) : "[Non dfini]"; villeTitle = (it["VilleTitle"] != null) ? it["VilleTitle"].ToString().Substring(it["VilleTitle"].ToString().IndexOf(";#") + 2) : "[Non dfini]"; villeSuperficie = it["VilleSuperficie"].ToString().Substring(it["VilleSuperficie"].ToString().IndexOf(";#") + 2); villeSuperficie = villeSuperficie.Substring(0, villeSuperficie.IndexOf(".")); paysSuperficie = it["PaysSuperficie"].ToString().Substring(it["PaysSuperficie"].ToString().IndexOf(";#") + 2); paysSuperficie = paysSuperficie.Substring(0, paysSuperficie.IndexOf(".")); paysHabitant = it["Habitants"].ToString().Substring(it["Habitants"].ToString().IndexOf(";#") + 2); paysHabitant = paysHabitant.Substring(0, paysHabitant.IndexOf(".")); Controls.Add(new LiteralControl(string.Format(@"<b>{0}</b> a t construit par <b>{1}</b> dans la ville de <b>{2}</b> ayant une superficie de <b>{3}</b> km en <b>{4}</b>.<br /> Ce pays compte <b>{5}</b> habitants pour une superficie de <b>{6}</b> km.<br /><br />", it["Title"], it["Entrepreneur"], villeTitle, villeSuperficie, paysTitle, paysHabitant, paysSuperficie)));

- 18 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog) }

Nous voulons rcuprer les lments dont la superficie du pays excde la valeur passe comme premier paramtre de la fonction et dont la superficie de la ville excde la valeur passe en deuxime paramtre. Pour ce qui est des jointures, des champs projets et des champs rcuprs, rien ne change. La diffrence se trouve dans la requte Where permettant de rcuprer les lments :
query.Query = string.Format("<Where>" + "<And>" + "<Geq>" + "<FieldRef Name='PaysSuperficie' />" + "<Value Type='Number'>{0}</Value>" + "</Geq>" + "<Geq>" + "<FieldRef Name='VilleSuperficie' />" + "<Value Type='Number'>{1}</Value>" + "</Geq>" + "</And>" + "</Where>", superficiePays, superficieVille);

Comme vous le voyez, cette requte est trs basique et extrmement simple. Elle effectue un And pour les conditions. La seule notion tenir l'il est qu'ici, nous pouvons utiliser le nom des champs projets pour effectuer les comparaisons. Cela ne cre donc aucun problme d'utiliser PaysSuperficie et VilleSuperficie pour effectuer les comparaisons. Appelez cette fonction de cette manire dans la fonction Page_Load :
AfficherMonumentsSelonSuperficie(50000, 5000); AfficherMonumentsSelonSuperficie(0, 200);

Ce qui aura pour effet d'afficher ceci :

- 19 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/

Join et ProjectedFields - Ralisation de jointures en CAML par Sbastien Sougnez (Home page) (Blog)

Les lments sont donc bien rcuprs en fonction des valeurs des superficies des villes et des pays. La premire fonction doit rcuprer les lments dont le pays a une superficie suprieure 50000 km et dont la ville a une superficie suprieure 5000 km. Il n'y a donc que la tour Eiffel qui apparat. L'autre requte, elle, rcupre tous les monuments dont le pays a une superficie suprieure 0 km (donc tous) mais il faut galement que la superficie de la ville soit suprieure 200 km, c'est--dire tous les lments galement. Comme vous avez pu le constater, le mcanisme de jointure de tables est trs simple. Si vous n'arrivez pas faire fonctionner l'exemple ci-dessus, nous vous invitons le tlcharger en cliquant sur le lien... ci-dessous. Tlcharger Un grand merci Wachter pour la relecture ainsi qu' Stephane Eyskens pour m'avoir indiqu cette nouveaut. Information sans laquelle je n'aurais pu faire ce tutoriel.

- 20 Copyright 2009 - Sbastien Sougnez. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://ssougnez.developpez.com/tutoriels/sharepoint/join-et-projectedfields-realisation-jointures-caml/