Partager via


Procédure : effectuer des requêtes à l’aide de LINQ to SharePoint

Dernière modification : vendredi 8 octobre 2010

S’applique à : SharePoint Foundation 2010

Dans cet article
Étape 1 : obtention d’une référence à un site Web
Étape 2 : obtention d’une référence à une liste
Étape 3 (facultative) : désactivation du suivi des modifications des objets
Étape 4 : définition de la requête LINQ
Étape 5 : énumération des résultats de la requête
Étape 6 (facultative) : fusion des résultats de plusieurs listes et de plusieurs sources de données
Étape 7 (facultative) : jointure de résultats provenant de plusieurs sources de données

Cette rubrique explique comment effectuer des requêtes sur des listes Microsoft SharePoint Foundation à l’aide du fournisseur LINQ to SharePoint.

Étape 1 : obtention d’une référence à un site Web

Tout le codage pour le fournisseur LINQ to SharePoint doit commencer par la création d’un objet DataContext. Cet objet représente un sous-ensemble d’une base de données de contenu, et en particulier les listes et les éléments de liste d’un site Web SharePoint Foundation. Le moyen le plus simple de créer un tel objet est de passer l’URL absolue du site Web qui fera l’objet des requêtes, en tant que chaîne littérale, au constructeur de la classe, comme dans cet exemple.

DataContext teamSite = new DataContext("http://MarketingServer/SalesTeam");

Cependant, la plupart du temps, votre solution devra s’exécuter pour de nombreux sites sur de nombreuses batteries de serveurs, et vous ne connaîtrez pas l’URL complète au moment d’écrire votre code. Si votre code s’exécute dans des situations où il y a un contexte HTTP, telles que dans un composant WebPart ou une page d’application personnalisée, et que vous effectuez des requêtes sur le site Web actuel, vous pouvez utiliser l’objet SPContext pour obtenir l’URL, comme le montre cet exemple.

DataContext teamSite = new DataContext(SPContext.Current.Web.Url);

Vous pouvez aussi utiliser le contexte pour obtenir indirectement les URL des autres sites Web de la collection de sites, ou même les autres collections de sites de l’application Web. Par exemple, le code suivant crée un contexte DataContext pour le site Web de plus haut niveau de la collection de sites la plus ancienne de l’application Web.

String rootOfOldestURL = this.Site.WebApplication.Sites[0].RootWeb.Url;      
using (DataContext topSiteOfOldestSiteCollection = new DataContext(rootOfOldestURL))
{
}

Notez que vous devez vous débarrasser de l’objet DataContext car il utilise un autre objet SPWeb que celui fourni par le contexte SPContext.

Notes

Les références à un objet SPWebApplication requièrent une instruction using (Imports en Visual Basic) pour l’espace de noms Microsoft.SharePoint.Administration.

Pour d’autres moyens permettant d’obtenir des références à un site Web dans une batterie de serveurs SharePoint Foundation, voir Obtention de références aux sites, applications Web et autres objets clés.

S’il n’existe pas de contexte HTTP, comme dans une application console, et que le nom du serveur n’est pas connu lorsque vous écrivez le code, vous pouvez utiliser l’alias « localhost » pour obtenir une référence au site Web racine, comme dans les exemples suivants.

using (DataContext topLevelSite = new DataContext("https://localhost"))
{
}

using (DataContext mySite = new DataContext("https://localhost/sites/MySite"))
{
}

Dans la mesure où il n’existe pas de contexte HTTP, vous devez vous débarrasser de l’objet DataContext.

Vous pouvez dériver une classe de DataContext, auquel cas vous allez utiliser le constructeur de votre classe, comme dans l’exemple qui suit.

ContosoTeamData teamSite = new ContosoTeamData(SPContext.Current.Web.Url);

Étape 2 : obtention d’une référence à une liste

Utilisez la méthode GetList<T>(String) pour obtenir un objet EntityList<TEntity>. Cet objet est une représentation IQueryable<T> d’une liste. Voici un exemple.

EntityList<Announcement> announcements = teamSite.GetList<Announcement>("Announcements")

Notez que le type de contenu de la liste doit être représenté par une classe explicitement déclarée, dans ce cas « Announcement ». La classe doit avoir un attribut ContentTypeAttribute qui spécifie le nom du type de contenu dans le site Web SharePoint Foundation et l’ID du type de contenu. En général, vous devriez savoir sur quelles listes votre code va effectuer des requêtes lorsque vous écrivez votre code. Au minimum, la classe qui représente le type de contenu doit inclure au moins une propriété qui représente une colonne de la liste, et cette déclaration de propriété doit avoir un attribut ColumnAttribute qui spécifie au moins le nom du champ et son type. L’exemple suivant montre les déclarations minimales requises pour permettre au code appelant d’appeler la méthode GetList<T>(String) (où T est Announcement).

[ContentType(Name="Announcement", Id="0x0104")]
public partial class Announcement
{
    [Column(Name = "Title", FieldType = "Text")] 
    public String Title { get; set; }
}

Cependant, une requête peut référencer seulement des colonnes qui sont représentées par des propriétés de la classe du type de contenu ; si seule cette déclaration minimale est effectuée, votre code appelant ne peut référencer que le champ (colonne) Title, comme le montre cet exemple.

var excitingAnnouncements = from announcement in announcements
                            where announcement.Title.EndsWith("!")
                            select announcement;

Notes

Comme le montre cet exemple, le fait que la classe soit nommée Announcement ne signifie pas qu’elle doit refléter exactement le type de contenu SharePoint Foundation du même nom. Cela signifie que vous n’êtes pas obligé d’avoir une propriété pour chaque colonne du type de contenu. La classe peut représenter seulement un sous-ensemble des colonnes du type de contenu, et elle peut aussi avoir des membres supplémentaires. Ceci est en fait une caractéristique très importante du fournisseur LINQ to SharePoint, car des colonnes peuvent être ajoutées aux listes par les propriétaires de site, et cette action crée en réalité un nouveau type de contenu pour la liste. La classe ne doit pas non plus avoir le même nom que le type de contenu de la liste. Elle peut porter n’importe quel nom, tant que ce nom est utilisé en tant que paramètre de type dans l’appel à la méthode GetList<T>(String). Votre code est cependant généralement plus lisible si la classe a le même nom que le type de contenu officiel de la liste. Par défaut, l’outil SPMetal suit cette pratique.

Les types de contenu peuvent hériter d’autres types de contenu et, pour l’appel à la méthode GetList<T>(String), vous pouvez utiliser comme paramètre de type tout type de contenu qui se trouve plus haut dans l’arborescence d’héritage. Par exemple, comme tous les types de contenu dérivent du type de contenu Item de base, vous pouvez utiliser Item en tant que paramètre de type, comme le montre cet exemple :

EntityList<Item> announcements = teamSite.GetList<Item>("Announcements")

Votre code source doit fournir une déclaration d’une classe Item, et cette classe doit déclarer des propriétés pour chacune des colonnes du type de contenu référencé par vos requêtes.

Si vous utilisez le type de contenu Item, vous pouvez effectuer des requêtes sur des listes sans connaître le nom de la liste ou de ses types de contenu dérivés lorsque vous écrivez votre code, comme le montre cet exemple.

DataContext topLevelSite = new DataContext("https://localhost");
SPSite siteCollection = new SPSite("https://localhost");
EntityList<Item> someList = topLevelSite.GetList<Item>(siteCollection.RootWeb.Lists[0].Title);

var first3Items = from item in someList
                  where item.Id <= 3
                  select item;

foreach (var item in first3Items)
{
    Console.Writeline("{0} is one of the first 3 items in {1}", item.Title, someList.Title);
}

Cependant, des scénarios plus réalistes de codage LINQ to SharePoint utile impliqueront les colonnes qui sont uniques dans des listes spécifiques ; en pratique, vous avez besoin de connaître les noms des listes et leurs types de contenu dérivés spécifiques. En particulier, lorsque vous écrivez du code, vous devez être à même de supposer que certaines listes sont présentes sur les sites Web qui feront l’objet des requêtes de votre code. En outre, comme vos requêtes sur une liste spécifiée référenceront des colonnes particulières, vous devez aussi être à même de supposer que, pour une liste donnée, un certain sous-ensemble de colonnes sera présent sur la liste. Ceci implique que votre solution SharePoint Foundation sera de l’un de ces deux types :

  • Elle sera conçue pour effectuer des requêtes sur des types de liste bien connus qui sont inclus avec SharePoint Foundation ou avec des produits ayant des fonctionnalités améliorées, tels que Microsoft SharePoint Server.

  • Elle sera développée en combinaison et installée avec un ensemble d’une ou plusieurs listes personnalisées en tant que composant d’un jeu de fonctionnalités ou d’une définition de site personnalisée.

Il est recommandé d’utiliser l’outil SPMetal pour générer les déclarations de classes et de propriétés nécessaires.

Étape 3 (facultative) : désactivation du suivi des modifications des objets

Si votre code effectue seulement des requêtes sur des listes au lieu d’ajouter, supprimer ou modifier des éléments de liste, vous pouvez désactiver le suivi des modifications des objets. Ceci améliorera les performances. Définissez la propriété ObjectTrackingEnabled à false.

teamSite.ObjectTrackingEnabled = false;

Étape 4 : définition de la requête LINQ

L’avantage de LINQ est que les requêtes sont écrites essentiellement de la même façon, indépendamment de la source de données ou du fournisseur LINQ. Excepté de légères différences dans la façon dont une référence au contexte des données et l’objet IQueryable<T> sont obtenus, les requêtes LINQ to SharePoint sont identiques aux requêtes que vous utiliseriez pour LINQ to SQL ou LINQ to XML. Pour plus d’informations, voir LINQ to SQL : Requête intégrée au langage .NET pour les données relationnelles (éventuellement en anglais) et LINQ to XML.

Cependant, deux fournisseurs LINQ donnés ne sont pas exactement identiques. Les différences dans les langages de requête natifs des sources de données (dans lesquels les requêtes LINQ sont traduites par le fournisseur) aboutissent parfois à différentes limitations des possibilités de requête. En particulier, il existe une limite sur les jointures de listes, qu’elles soient implicites ou explicites, dans les requêtes utilisant le fournisseur LINQ to SharePoint. Une requête LINQ to SharePoint peut effectuer une jointure sur deux listes, explicitement ou implicitement, mais seulement si une des listes a un type de colonne Recherche qui effectue une recherche dans une colonne de l’autre table. Si le champ de recherche n’autorise qu’une seule valeur, cette relation entre les listes doit être représentée dans votre code avec un champ EntityRef<TEntity> dans la classe qui représente le type de contenu de la liste. Si le champ autorise des valeurs multiples, la relation doit être représentée avec un champ EntitySet<TEntity> et une propriété EntitySet<TEntity> qui l’inclut.

ConseilConseil

La propriété Log est un TextWriter qui peut écrire la requête CAML en laquelle est traduite votre requête LINQ. La possibilité de voir la requête CAML peut être utile lors du débogage. Pour cela, affectez un objet TextWriter à la propriété Log. Dans l’exemple suivant, OutTextWriter est affecté à Log. Ceci fait que la requête CAML apparaît sur la console lorsqu’une requête LINQ est exécutée dans une application console, comme montré ici.

#if DEBUG
teamSite.Log = Console.Out;
#endif

Étape 5 : énumération des résultats de la requête

Comme avec tous les fournisseurs LINQ, une requête LINQ to SharePoint n’est pas exécutée tant qu’elle n’est pas énumérée. Ceci se produit généralement dans une boucle foreach. Dans le cas rare où vous voulez une énumération personnalisée, par exemple ignorer tous les autres éléments dans le résultat, vous pouvez utiliser les méthodes de IEnumerable et IEnumerator.

Vous pouvez aussi affecter les résultats de la requête à une variable IEnumerable<T> telle qu’un objet IList<T> ou ICollection<T>, au lieu du type anonyme var (Dim en Visual Basic). Ceci fait que la requête s’exécute immédiatement pour alimenter la variable. Voici un exemple :

EntityList<Announcement> announcements = teamSite.GetList<Announcement>("Announcements")

IList<Announcement> excitingAnnouncements = from announcement in announcements
                                            where announcement.Title.EndsWith("!")
                                            select announcement;

Étape 6 (facultative) : fusion des résultats de plusieurs listes et de plusieurs sources de données

Vous pouvez fusionner les résultats de plusieurs listes en une seule liste IList<T> que vous pouvez ensuite filtrer à l’aide de LINQ to Objects. L’exemple suivant montre comment produire une liste IList<T> des événements d’une entreprise et d’une équipe, et comment générer un rapport des événements du jour dans un auditorium.

DataContext corpSiteData = new DataContext("https://localhost/CorpSite");
DataContext markTeamData = new DataContext("https://localhost/Marketing");

EntityList<Event> allCorpEvents = corpSiteData.GetList<Event>("Calendar");
EntityList<Event> allMarkTeamEvents = markTeamData.GetList<Event>("Calendar");

List<Event> todaysCorpEvents = (from ev in allCorpEvents
                  where ev.StartDate = DateTime.Now
                  select ev).ToList();

List<Event> todaysTeamEvents = (from ev in allMarkTeamEvents
                  where ev.StartDate = DateTime.Now
                  select ev).ToList();

IEnumerable<Event> mergedEvents = todaysCorpEvents.Union(todaysTeamEvents);

var todaysAuditoriumEventTitles = from ev in mergedEvents
                  where ev.Location.Contains("Auditorium")
                  select new { ev.Title };

foreach (var eventTitle in todaysAuditoriumEventTitles)
{
    Console.WriteLine(eventTitle.Title);
}

Les deux objets IList<T> doivent avoir le même paramètre de type.

Étape 7 (facultative) : jointure de résultats provenant de plusieurs sources de données

La technique utilisée dans l’étape 7 pour fusionner des données provenant de plusieurs listes SharePoint Foundation peut être utilisée pour fusionner des données provenant de plusieurs listes SharePoint Foundation avec des données provenant d’autres sources, à condition que les enregistrements de l’autre source puissent faire l’objet d’une conversion de type avec la classe représentant le type de contenu SharePoint Foundation. Par exemple, supposons que votre code utilise LINQ to SQL pour produire un objet IList<T> (où T est Client) nommé oldClients et supposons aussi qu’il utilise LINQ to SharePoint pour produire un objet IList<T> (où T est Patient) nommé activePatients. Si les propriétés et les autres membres de la classe Client sont un sous-ensemble des membres de la classe Patient et que les membres correspondants ont les mêmes signatures, vous pouvez fusionner les données provenant de la source SQL avec les données provenant de la liste SharePoint Foundation comme cela est montré dans cet exemple.

foreach (Patient patient in activePatients)
{
    oldClients.Add((Client)patient);
}

Une option encore meilleure lorsque vous devez fusionner des données provenant de fournisseurs LINQ différents est d’utiliser la même classe de types d’éléments pour les deux fournisseurs. Ceci est possible car vous pouvez placer les attributs nécessaires pour LINQ to SharePoint et ceux qui sont nécessaires pour un autre fournisseur LINQ sur la même déclaration de classe. L’exemple suivant montre la signature d’une déclaration de classe avec l’attribut ContentTypeAttribute de LINQ to SharePoint et l’attribut TableAttribute de LINQ to SQL.

[ContentType(Name="Item", Id="0x01" List="Customers")]
[Table(Name = "Customers")]
public partial class Customer : Item
{
}

Avec ces attributs à cet endroit, aucune conversion de type n’est nécessaire pour fusionner des données provenant de la table SQL avec les données provenant de la liste SharePoint Foundation.

Voir aussi

Référence

SPMetal

ColumnAttribute

ContentTypeAttribute

DataContext

EntityList<TEntity>

EntityRef<TEntity>

EntitySet<TEntity>

ICollection<T>

IEnumerable

IEnumerator

IList<T>

IQueryable<T>

SPContext

SPWebApplication

TableAttribute

Concepts

ID de type de contenu

Requêtes LINQ non prises en charge et requêtes en deux étapes

Obtention de références aux sites, applications Web et autres objets clés

Procédure : écrire dans les bases de données de contenus en utilisant LINQ to SharePoint

Autres ressources

LINQ to Objects

LINQ to SQL : Requête intégrée au langage .NET pour les données relationnelles (éventuellement en anglais)

LINQ to XML

Vue d'ensemble des composants WebPart