Partager via


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

Dernière modification : jeudi 22 septembre 2011

S’applique à : SharePoint Foundation 2010

Dans cet article
Requêtes non prises en charge
Requêtes en deux étapes
Cas dans lequel la distinction n’a aucune importance

Cette rubrique présente certains types de requêtes LINQ (Language Integrated Query) qui ne sont pas pris en charge par le fournisseur LINQ to SharePoint. Elle décrit également le processus composé de deux étapes utilisé pour les requêtes qui emploient des opérateurs LINQ ne pouvant pas être convertis en Langage CAML (Collaborative Application Markup Language) par le fournisseur LINQ to SharePoint.

Requêtes non prises en charge

Certains types de requêtes disponibles dans la syntaxe LINQ de C# et Visual Basic qui fonctionnent correctement dans des contextes donnés pour certains types de sources de données donnent des résultats insatisfaisants lorsqu’ils sont utilisés avec les données d’un site Web Microsoft SharePoint Foundation. Ces types de requêtes ne sont pas pris en charge par le fournisseur LINQ to SharePoint, notamment les requêtes qui demandent plusieurs requêtes distinctes sur la base de données de contenu. Par exemple, si une requête sur la Table A demande une autre requête sur la Table B pour chaque ligne de la Table A, la requête sur la Table A n’est pas prise en charge. De même, l’utilisation du mot clé LINQ union, comme illustré dans l’exemple ci-après, n’est pas prise en charge et générerait une exception car elle demande des requêtes distinctes sur deux listes.

DataContext data = new DataContext("http://ContosoServer");            DataContext juniorData = new DataContext("http://ContosoServer/JuniorTeamSite");

EntityList<Announcement> Announcements = data.GetList<Announcement>("Announcements");
EntityList<Announcement> JuniorAnnouncements = juniorData.GetList<Announcement>("Announcements");

var seniorAnns = from ann in Announcements
                 select ann;

var juniorAnns = from ann in JuniorAnnouncements
                 select ann;

IEnumerable<Announcement> mergedAnns = seniorAnns.union(juniorAnns);

foreach (Announcement ann in mergedAnns)
{
    Console.WriteLine(ann.Title);
}

Une des conséquences de cette règle est que les requêtes qui supposent une jointure implicite entre deux listes SharePoint Foundation ne sont prises en charge que si le champ de jointure est configuré en tant que champ de recherche.

Requêtes en deux étapes

Certaines requêtes LINQ ne peuvent pas être entièrement converties en CAML. Ces requêtes peuvent toutefois fonctionner correctement, car elles peuvent être exécutées en deux étapes. Premièrement, le fournisseur LINQ to SharePoint convertit la plus grande partie possible de la requête en CAML, puis il l’exécute. Cela produit un sur-ensemble de données qui est passé de la base de données de contenu au serveur Web frontal en tant qu’objet IEnumerable<T>. Deuxièmement, les parties restantes de la requête sont recomposées en requête LINQ to Objects sur l’objet IEnumerable<T>. (La première étape, mais doit être exécutable avec une seule requête sur la base de données de contenu ou toute la requête génère une exception.

Comme exemple de requête en une étape, imaginez une clause select LINQ telle que « select new { c.Name, c.ZipCode } ». Elle peut être convertie en CAML comme balise <ViewFields (éventuellement en anglais)> avec deux éléments enfants <FieldRef (éventuellement en anglais)>. Toutefois, la clause « select new { c.Price*2, c.Orders, c.Customer } » contient une fonction mathématique qui n’est pas prise en charge dans CAML. Le requête est donc convertie par le fournisseur LINQ to SharePoint et exécutée jusqu’à la clause select seulement. Les résultats reçus de la requête CAML sont ensuite envoyés au serveur Web frontal en tant qu’objet IEnumerable<T>. Une nouvelle requête LINQ sur le serveur Web frontal exécute ensuite la projection de clause select sur l’objet à l’aide de la méthode Enumerable.Select() LINQ to Objects.

Il n’existe pas de méthode simple pour spécifier des opérateurs LINQ qui ne sont pas pris en charge ou qui requièrent deux étapes. Par exemple, l’opérateur Union(), comme illustré ci-dessus, n’est pas pris en charge si les deux sources de données qui sont en train d’être fusionnées correspondent à des listes de la base de données de contenu. En revanche, si seule une source de données correspond à une liste SharePoint Foundation et que l’autre source de données correspond à une table déjà en mémoire, l’opérateur Union() peut être utilisé.

En général, les méthodes de requête nécessitant des opérations mathématiques requièrent. Il existe toutefois des exceptions lorsque le fournisseur LINQ to SharePoint peut récupérer une valeur du modèle objet SharePoint Foundation. Par exemple, les méthodes Count() et LongCount() ne requièrent pas la division de la requête en deux étapes.

Les opérateurs ci-dessous requièrent en règle générale deux étapes et fonctionnent normalement, à condition que la première étape ne demande qu’une seule requête de la base de données de contenu.

Cas dans lequel la distinction n’a aucune importance

Si vous écrivez la sortie des parties de la requête pouvant être converties en CAML dans un objet IEnumerable<T> au moyen des méthodes ToList<TSource>(IEnumerable<TSource>), ToDictionary() ou ToArray<TSource>(IEnumerable<TSource>), la partie de la requête se trouvant après l’appel de l’une de ces méthodes utilise les opérateurs de requête de la classe Enumerable au lieu de la classe Queryable. Dans ce cas, la distinction entre les requêtes à une étape et celles à deux étapes n’a aucune importance.

Comparez par exemple les deux requêtes ci-dessous. Elles devraient être toutes deux des requêtes à deux étapes en raison de l’utilisation de l’opérateur mathématique « - ». La deuxième requête rend ceci explicite, car le fournisseur LINQ to SharePoint n’est utilisé que dans la ligne from, qui lit les « commandes » de toute la liste en IList<T>.

var ordersInArrears = from order in orders
                      where order.Price – order.Paid > 0
                      select order;

var ordersInArrears = from order in orders.ToList()
                      where order.Price – order.Paid > 0
                      select order;

Diviser manuellement vos requêtes en une partie LINQ to SharePoint et une partie LINQ to Objects vous permet également d’utiliser des mots clés LINQ qui ne seraient autrement pas pris en charge. Par exemple, la version ci-après de la tentative de fusion de deux ensembles d’annonces fonctionnerait, car les requêtes LINQ to SharePoint sont énumérées séparément dans deux objets IEnumerable<T>. Le mot clé union utilisé est la version LINQ to Objects de Union().

DataContext data = new DataContext("http://ContosoServer");            DataContext juniorData = new DataContext("http://ContosoServer/JuniorTeamSite");

EntityList<Announcement> Announcements = data.GetList<Announcement>("Announcements");
EntityList<Announcement> JuniorAnnouncements = juniorData.GetList<Announcement>("Announcements");
List<Announcement> seniorAnns = (from ann in Announcement
                                 select ann).ToList();

List<Announcement> juniorAnns = (from ann in JuniorAnnouncements
                                 select ann).ToList();

IEnumerable<Announcement> mergedAnns = seniorAnns.union(juniorAnns);

foreach (Announcement ann in mergedAnns)
{
    Console.WriteLine(ann.Title);
}

Voir aussi

Référence

IEnumerable<T>

Select

Autres ressources

LINQ to Objects