IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[Avancé] Conseils, discussions : Rendre les requête sql/linq génériques


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 198
    Points : 106
    Points
    106
    Par défaut [Avancé] Conseils, discussions : Rendre les requête sql/linq génériques
    Bonjour,

    J'ai rencontré pas mal de fois un même cas de figure donc je me suis dis qu'il devait y avoir une best practice voir un pattern.

    En effet, il n'est pas rare d'avoir une source de donnée (ex: une base de donnée) et de devoir filtrer un resultat (ex: requête sql/linq) selon des paramètres( ex: champs, colonnes) variables et dynamique, on peut également vouloir afficher le résultat en affichant que certains attributs.

    Prenons un exemple concret.

    On a une gridview et une série de filtre sur chaque champ de la base de données. Les filtres peuvent être utilisés ou non.

    Typiquement le code ressemble à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    string request = " SELECT FieldA, FieldB, ... FROM TABLE WHERE ";
                if (!string.IsNullOrEmpty(field1))
                    requete += String.Format(" FIELDA  = {0}", field1);
                if (!string.IsNullOrEmpty(field2))
                    requete += String.Format(" FIELDB  = {0}", field2);
    ....
    La gestion du WHERE peut vite devenir compliqué avec les ET et les OU. Pareil pour rendre le SELECT dynamique en fonction des champs que l'on veut voir.
    La gestion de se long string qui est la requête est affreuse et difficilement maintenable pour les grosses requetes

    De mon expérience, j'aurai tendance à créer une classe TableSelector, de manière à rendre ca plus facilement maintenant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        class TableSelector
        {
            private EnumerableRowCollection<DataRow> _queryLINQ; // dans le cas de linq
            private string _querySQL;// dans le cas de sql
     
            public void AddFilter(string column, string value)
            {
                _queryLINQ = from x in Tables where x.fields[column] = value;
            }
     
            public List<> GetResult(Array<string> column)
     
        }

    J'aimerais connaitre votre façon de faire, vos avis, si vous avez des discussions ou des blogs la dessus etc ...

    Merci :-)

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Quand on génère du SQL à la main, ça finit toujours par donner des trucs dégueulasses, surtout pour les requêtes complexes avec des critères variables. J'en sais quelque chose, j'ai bossé pendant 2 ans sur une appli où le cas se présentait tout le temps, c'était un vrai cauchemar à gérer

    Si tu peux, essaie d'utiliser Linq (Linq to SQL ou Entity Framework), ça donne déjà des trucs beaucoup plus propres.

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    IQueryable<Customer> query = db.Customers;
    if (!string.IsNullOrEmpty(prenom))
        query = query.Where(c => c.FirstName == prenom);
    if (!string.IsNullOrEmpty(nom))
        query = query.Where(c => c.LastName == nom);
    ...
     
    foreach(Customer c in query)
    {
         ...
    }
    Fini le SQL dégueulasse
    Dans l'exemple ci-dessus, ça revient à faire des "AND" entre les critères. Pour des cas plus compliqués, avec des OU par exemple, tu peux utiliser PredicateBuilder pour construire les conditions


    Si tu n'as pas la possibilité d'utiliser Linq, c'est plus galère... une classe dédiée peut effectivement être une bonne solution de rechange.

    Petite en passant, tu devrais aussi utiliser des requêtes paramétrées pour éviter les problèmes de format et de sécurité (injection SQL)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 198
    Points : 106
    Points
    106
    Par défaut
    C'est malheureusement une DB access donc pas de linq to sql. Ce que je fais maintenant pour utiliser du linq est donc une classe Selector avec ceci dans le constructeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    DataTable badges = DataProvider.CreateDataSet(cmd).Tables[0];
     
     
                _query = from b in badges.AsEnumerable()
                         select b; // _query est un attribut de type EnumerableRowCollection<DataRow>

    Tu vois une autre manière avec une DB access pour travailler avec du LINQ ?
    Tu penses que c'est superflux ma classe Selector si on utilise LINQ ?

    Merci pour les requêtes paramétrés, je les utilise habituellement mais la j'ai voulu faire vite un exemple.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par AsPrO Voir le message
    C'est malheureusement une DB access donc pas de linq to sql. Ce que je fais maintenant pour utiliser du linq est donc une classe Selector avec ceci dans le constructeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    DataTable badges = DataProvider.CreateDataSet(cmd).Tables[0];
     
     
                _query = from b in badges.AsEnumerable()
                         select b; // _query est un attribut de type EnumerableRowCollection<DataRow>
    Effectivement Linq to DataSet est une option viable, si le volume de données n'est pas trop important (vu que les données sont chargées en mémoire)

    Citation Envoyé par AsPrO Voir le message
    Tu penses que c'est superflux ma classe Selector si on utilise LINQ ?
    Oui, ça me semble tout à fait superflu... je ne vois pas ce que ça apporte que tu ne pourrais pas faire plus facilement directement avec Linq to DataSet

    Citation Envoyé par AsPrO Voir le message
    Tu vois une autre manière avec une DB access pour travailler avec du LINQ ?
    A priori NHibernate est compatible avec Access, et ça supporte Linq depuis la v3 il me semble.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 198
    Points : 106
    Points
    106
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Oui, ça me semble tout à fait superflu... je ne vois pas ce que ça apporte que tu ne pourrais pas faire plus facilement directement avec Linq to DataSet
    .
    En fait l'utilité que j'en vois est de centraliser la partie "requête" ( que ca soit du sql ou du linq) de façon à ce que ca reste indépendant du code. De cette manière le code appelle juste une methode AddFilter et GetResult sans savoir ce qu'il y a derrière. De plus pour dans le cas de LINQ to Dataset, j'ai obligatoirement besoin d'avoir au moins une requête SQL ( SELECT * FROM Table ), sauf si quelque chose m'échappe.

    Mais peut-être que pour toi ca ne justifie pas la "complexité" que ca apporte ?


    Super pour Nhibernate, je connais que de nom mais je vais investiguer !

Discussions similaires

  1. [PHP 5.3] conseil sur les requêtes SQL en MVC
    Par grinder59 dans le forum Langage
    Réponses: 24
    Dernier message: 25/08/2014, 20h45
  2. LINQ to SQL] Tracer les requêtes SQL d'Insert/Update/Delete
    Par annalady dans le forum Accès aux données
    Réponses: 5
    Dernier message: 30/07/2009, 10h17
  3. [D5][BDE][Multibase] Récupérer les requêtes SQL d'une TTable
    Par Escandil dans le forum Bases de données
    Réponses: 3
    Dernier message: 11/01/2006, 14h29
  4. [iBatis] Logger les requètes SQL
    Par bslota dans le forum Persistance des données
    Réponses: 2
    Dernier message: 25/11/2005, 14h29
  5. tracer les requêtes SQL
    Par izioto dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 13/10/2005, 16h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo