Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

LINQ : une nouvelle façon de concevoir les algorithmes

Il y a plusieurs façon d'optimiser le code :

  • Faire le code le plus rapide à l'exécution
  • Faire le code le plus rapide à l'écriture
  • Faire le code le plus lisible
  • etc.

Comme l'optimisation est donc une notion très relative, je ne vais pas m'en soucier dans les requêtes LINQ suivantes.

Imaginons le cas suivant : 

private const string displayXml = @"<?xml version=""1.0"" encoding=""UTF-8""?><Displays><Display>Address1</Display><Display>TheatreName</Display><Display>Address2</Display><Display>City</Display></Displays>";

et un résultat :

string result = @"<NewDataSet>

                <SearchResults>

                  <TheatreID>3528</TheatreID>

                  <TheatreName>AMC OAK PARK PLAZA 6</TheatreName>

                  <Address1>9747 QUIVIRA RD</Address1>

                  <City>SHAWNEE MISSION</City>

                  <StateAbbr>KS</StateAbbr>

                  <ZipPlus4>66215</ZipPlus4>

                  <InterceptMarket>SHAWNEE MISSION</InterceptMarket>

                </SearchResults>

                <SearchResults>

                  <TheatreID>5135</TheatreID>

                  <TheatreName>AMC OAK TREE 6</TheatreName>

                  <Address1>10006 AURORA AVE N</Address1>

                  <City>SEATTLE</City>

                  <StateAbbr>WA</StateAbbr>

                  <ZipPlus4>98133</ZipPlus4>

                  <InterceptMarket>SEATTLE</InterceptMarket>

                </SearchResults>

                <SearchResults>

                  <TheatreID>7821</TheatreID>

                  <TheatreName>AMC OAKVIEW 24</TheatreName>

                  <Address1>3555 S 140TH PLZ</Address1>

                  <City>OMAHA</City>

                  <StateAbbr>NE</StateAbbr>

                  <ZipPlus4>68144</ZipPlus4>

                  <InterceptMarket>OMAHA</InterceptMarket>

                </SearchResults>

              </NewDataSet>";

On veut récupérer le résultat en fonction de sa constante : il fallait que les éléments soient classés dans le même ordre que dans sa constante.

La requête LINQ To XML suivante fera très bien l'affaire :

var newXml = new XElement("NewDataSet",

    from searchResult in XElement.Parse(result).Descendants("SearchResults")

    select new XElement("SearchResults",

        from display in XElement.Parse(displayXml).Descendants("Display")

        select searchResult.Element(display.Value)));

Complexifions un peu ça. Après avoir récupérer ces éléments displayXml, il faudrait rajouter les éléments non présents dans la constante. Comment faire ceci ?

La façon la plus naturelle, à mon sens, (avec LINQ) est la suivante :

var newXml = new XElement("NewDataSet",

    from searchResult in XElement.Parse(result).Descendants("SearchResults")

    let displayXmlElement = XElement.Parse(displayXml)

    select new XElement("SearchResults",

        (from display in displayXmlElement.Descendants("Display")

         select searchResult.Element(display.Value)).Union(

        from searchResultElement in searchResult.Elements().Select(sre => sre.Name.LocalName)

        where !displayXmlElement.Descendants("Display").Select(dxe => dxe.Value).Contains(searchResultElement)

        select searchResult.Element(searchResultElement))));

Petite remarque au passage, avec le constructeur du XElement, on peut se passer de l'Union :

var newXml = new XElement("NewDataSet",

    from searchResult in XElement.Parse(result).Descendants("SearchResults")

    let displayXmlElement = XElement.Parse(displayXml)

    select new XElement("SearchResults",

        from display in displayXmlElement.Descendants("Display")

        select searchResult.Element(display.Value),

        from searchResultElement in searchResult.Elements().Select(sre => sre.Name.LocalName)

        where !displayXmlElement.Descendants("Display").Select(dxe => dxe.Value).Contains(searchResultElement)

        select searchResult.Element(searchResultElement)));

Cependant, on peut également pensé autrement : mettre tous les éléments dans la constante puis remettre tous les éléments et enlever les doublons. Ce qui donne :

var newXml = new XElement("NewDataSet",

    from searchResult in XElement.Parse(result).Descendants("SearchResults")

    select new XElement("SearchResults",

        (from display in XElement.Parse(displayXml).Descendants("Display")

        select searchResult.Element(display.Value)).Union(searchResult.Elements()).Distinct()));

 

Cette dernière requête est beaucoup plus lisible que la précédente.Cependant, on peut également

 

Le but de post n'est bien entendu pas de montrer ce que tout le monde sait : pour un même problème, il y a plusieurs solutions. Le but recherché ici est de montrer comment LINQ permet de gagner en lisibilité avec du code "moins naturelle".

 

Prenons un autre exemple : dans Northwind, imaginons qu'on veuille récupérer pour chaque produit le client en ayant acheté la plus grande quantité avec la quantité.

 

Si on utilise LINQ en "mode algorithme classique", on va écrire la requête suivante :

 

from p in context.Products

let info = (from c in context.Customers

            let quantity =

                (from o in c.Orders

                 select

                    (from od in o.Order_Details

                     where od.Product == p

                     select (int)od.Quantity).Sum()).Sum()

            orderby quantity descending

            select new { Customer = c, Quantity = quantity }).First()

select new { Product = p, info.Customer, info.Quantity };

 

Si on utilise LINQ en "mode requête", on va plutôt écrire la requête suivante :

 

from p in context.Products

let info = (from od in p.Order_Details

            group od by od.Order.Customer into odByCust

            let quantity = odByCust.Sum(od => (int)od.Quantity)

            orderby quantity descending

            select new { Customer = odByCust.Key, Quantity = quantity }).First()

select new { Product = p, info.Customer, info.Quantity };

 

Après c'est à vous de décider vers quel critère d'optimisation vous voulez vous orienter.

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 :

Publié vendredi 21 mars 2008 01:59 par Matthieu MEZIL

Classé sous : , , , ,

Commentaires

Pas de commentaires

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