Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

[Linq To WIQL] Les dessous du provider (Part 1: introduction)

Lors de l'écriture d'un provider LINQ, il faut sans cesse essayer d'adapter la souplesse de la syntaxe LINQ avec les contraintes du langage de requête cible.  Ce post est le premier d'une série sur les différents problèmes que j'ai rencontrés et que je rencontre encore lors du développement du provider Linq pour WIQL pour Fissum, le WIQL étant le "Work Item Query Langage" utilisé par Team Foundation Server pour attaquer la base de workitem du serveur.

Pour bien comprendre où j'en suis je vous conseille de lire la série (au moins les 3 premiers) de billets dédié à l'écriture d'un provider Linq To SQL par Matt Warren:

Cela suffit à peu près pour Linq To WIQL: le langage a tellement de contraintes que la plupart des fonctionnalités de Linq ne sont pas supportées!

Je reviens sur mon problème: le gros du développement de ce provider est concentré dans la traduction de la clause Where de la requête. Pour cela j'utilise la classe ExpressionVisitor qui est décrite dans la partie 2 des billets de Matt. Au visiteur, je lui associe une classe qui va me permettre de construire le corps de ma requête en WIQL: le QueryBuilder. Essentiellement cette classe garde en mémoire les différents morceaux de la requête pour les compiler à la fin de la traduction.

Voici un exemple des règles à respecter: WIQL supporte les opérateurs binaires, donc pour chaque opérateur binaire je lui associe l'opérateur WIQL associé. WIQL supporte:

  • les opérateurs binaires AND OR (pas le NOT!)
  • les opérateurs de comparaison: <,>, <>,= >=,<=
  • des opérateurs spécifiques comme "ever" "contains"

Autre contrainte: pour un opérateur de comparaison, "a == b" par exemple "a" est forcément un champ du work item et "b" une valeur.

Voici un exemple de requète LINQ To WIQL et sa traduction en WIQL:

var q = from wi in server.WorkItems()

        where

           (wi.Title.Contains(searchString) ||

           wi.History.Contains(searchString) ||

           wi.Description.Contains(searchString)) &&

           wi.Field<string>(SystemField.AssignedTo) == QueryConstant.Me

        orderby wi.CreatedDate descending, wi.Title

        select wi;

 

SELECT [System.Id]
FROM WORKITEMS
WHERE (((([System.Title] contains @P0 OR [System.History] contains @P1) OR [System.Description] contains @P2) AND ([System.AssignedTo] = @Me)))
ORDER BY [System.CreatedDate] desc, [System.Title] asc

Comme je le disais plus haut la syntaxe est étrangement équivalente! Je ne m'attarde pas sur la clause SELECT du WIQLqui n'est pas nécessaire pour le provider, c'est pour cela que je renvoie toujours l'id du work item car dans tout les cas, l'API qui exécutera la requête renverra toujours un workitem complet.

La clause ORDER BY est aussi très simple, j'expliquerai dans un autre billet comment traduire les propriétés en champs de workitem. De la même façon dans la clause WHERE l'appel à Field<T> a aussi été traduit en champs. On peut remarquer aussi que les appels à "Contains" de la classe String sont traduits en l'opérateur WIQL "contains".

Pour résumé: LINQ permet l'utilisation naturelle des API du Framework .Net tout en les transposant dans le langage cible. Plus on utilise ces fonctionnalités, plus l'utilisation du provider sera efficace.

A bientôt pour la suite :)

Publié lundi 1 décembre 2008 12:00 par Miiitch
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# re: [Linq To WIQL] Les dessous du provider (Part 1: introduction)

Pourquoi être parti sur un provider basé sur le pattern IQueryable si le provider ne supporte qu'un petit nombre d'opérations Linq ?

Pour avoir écris le provider Linq to db4o [1], qui concrètement n'optimise que le Where et les OrderBy/ThenBy, c'était bien plus simple de ne pas passer par IQueryable et d'avoir mes propres opérations Linq. Ce qui en plus permet de retomber sur LINQ to Objects dès qu'une opération n'est plus supportée par le provider, au lieu d'avoir à appeler AsEnumerable.

[1] https://source.db4o.com/db4o/trunk/db4o.net/Db4objects.Db4o.Linq/

lundi 1 décembre 2008 12:35 by Jb Evain

# re: [Linq To WIQL] Les dessous du provider (Part 1: introduction)

Quand je parle d'opérations non supportés, je parle des jointures ou des groupements. Par contre j'utilise au maximum (enfin presque!) les possibilités que m'offre la manipulation de l'arbre d'expressions pour transformer du code en opérateurs WIQL qui n'existent pas en .Net.

Quant à ta question sur le pourquoi utiliser Linq si je ne l'utilise pas entièrement, je te dirais que c'est pour la même raison que beaucoup de personnes utilisent .Net à peut-être 10% de ses fonctionnalités: car cela répond à leurs besoins, même si c'est que 10% du Framework.

lundi 1 décembre 2008 22:37 by Miiitch

# re: [Linq To WIQL] Les dessous du provider (Part 1: introduction)

Je crois que ma question n'a pas été comprise :)

Je reformule.

Ce post laisse entendre que pour développer votre provider LINQ to WIQL, vous vous êtes basés sur le pattern IQuerable

<T>. Vous dites aussi que vous ne traduisez qu'une partie des opérateurs LINQ.

Ma question est donc, pourquoi se baser sur IQueryable<T>, qui est l'approche «lourde» de l'écriture d'un provider LINQ ?

Ayant moi même écris un provider LINQ, en utilisant une autre approche (avec une comparaison des différentes approches dans la section 3. Extending on LINQ de la page: http://blogs.msdn.com/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx): créer soit même son type «receveur» des expressions trees, au lieu de supporter toute l'infrastructure de IQueryable, je me pose la question de pourquoi votre choix.

Donc c'est une question technique bête et méchante, qu'est ce qui a motivé cette direction ?

Mais il ne me semble pas avoir demandé pourquoi utiliser LINQ, avoir implémenté LIQN to objects et les Expression Trees dans Mono, je suis moi même assez convaincu de son utilité hein.

lundi 1 décembre 2008 23:09 by Jb Evain

# re: [Linq To WIQL] Les dessous du provider (Part 1: introduction)

ha ;)

J'ai besoin de l'arbre d'expression entier car je réalise des transformations à la fois dans le from le where et le order:

* dans le from: mon interface IQueryable

<T> peut provenir d'un Team project ou d'un serveur complet; dans le premier cas j'ajoute une clause where (et oui dans WIQL on peut avoir autant de where que l'on veut!) avec un filtre sur le projet

* dans le order comme le where, l'interprete des appels de la méthode "Field" en les traduisants en champs.

J'ai donc une méthode commune de fonctionnement pour toutes ces parties. Autre raison: je n'ai pas un accès direct aux données des work items, et donc le tri peut ne pas être performant: il ne faut pas oublier que derrière on a du web service!!

lundi 1 décembre 2008 23:26 by Miiitch
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01