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

Bases de données Delphi Discussion :

Où placer les sources SQL


Sujet :

Bases de données Delphi

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    566
    Détails du profil
    Informations personnelles :
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2009
    Messages : 566
    Points : 1 045
    Points
    1 045
    Par défaut Où placer les sources SQL
    Bonjour,

    Je voudrais votre avis sur la méthode que vous utilisez pour placer le code source SQL des requêtes. Il faut savoir que je travaille uniquement en SQL et que les query sont créés dynamiquement lors de l'utilisation de l'unité concernée.

    Mes outils sont Firebird 2. 14 et Delphi 7 ou Delphi 2010 (en rodage).

    J'ai fait de nombreux essais, mais aucun ne me donne entière satisfaction.

    Actuellement, je mets mes sources SQL dans chacune des unités où elles sont utilisées. Ces sources des requêtes sont les dernières lignes de l'unité.

    Pour en assurer la gestion, j'ai écrit la fonction suivante dans chaque unité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function TfrmSaisirFactEcrit.f_LireSql(pReqStr: string): string;
    const
      kEcriture_W01 =         // Insérer une écriture - Rapprochement toujours à 0
        'INSERT INTO ECRITURE (BANQ_ID, OPERAT_ID, ECRIT_DATE, ECRIT_LIB, ECRIT_D_C, ECRIT_VALEUR) ' +
           'VALUES(:pBanqId, :pOperat, :pDate, :pLib, :pEcrit, :pValeur) RETURNING ECRIT_ID ';
     
      kLiaison_W01 =         // Créer liaison entre la facture et l'opération financière ECRITURE <=> FACTURE
        'INSERT INTO ENCAISSER (BANQ_ID, ECRIT_ID, FACT_ID) VALUES(:pBanqId, :pEcritId, :pFactId) ';
     
      kEcriture_M01 =        // Modifier une écriture - Elle ne doit pas être comptabilisée
        'UPDATE ECRITURE SET BANQ_ID = :pBanqId, OPERAT_ID = :pOperat, ECRIT_DATE = :pDate, ECRIT_LIB = :pLib, ECRIT_D_C = :pEcrit, ECRIT_VALEUR = :pValeur ' +
        'WHERE ECRIT_ID = :pEcritId ';
     
      kFacture_M01 =        // Modifier la date d'échéance de la facture pour la mettre en corrélation avec l'encaissement prévisionnel
        'UPDATE FACTURE SET FACT_ECH = :pDate WHERE FACT_ID = :pFactId ';
     
    begin
      case AnsiIndexStr(pReqStr, ['kEcriture_W01', 'kLiaison_W01', 'kEcriture_M01', 'kFacture_M01']) of
        0: Result := kEcriture_W01;
        1: Result := kLiaison_W01;
        2: Result := kEcriture_M01;
        3: Result := kFacture_M01;
      end;
    end;
    Cette approche me donne satisfaction, mais elle présente quelques inconvénients.

    • Répétition de certaines requêtes dans plusieurs unités ;
    • Augmentation du volume des sources ;
    • Toute correction nécessite une recompilation.

    J'ai fait des essais avec un fichier xml, mais il faut mettre en place une mécanique qui peut se bloquer lorsque nous travaillons en réseau, sauf à mettre un fichier xml sur chaque poste. Dans cette situation, il faut gérer les mises à jour.

    Ma dernière idée serait de mettre l'ensemble des requêtes dans une table spécifique de la base de données et d'en faire une lecture complète à l'ouverture du programme dans un TClientDataSet. Elle serait stockée en mémoire pendant l'utilisation de l'application.

    Merci de me donner votre avis sur cette approche et éventuellement me dire la méthode que vous utilisez, sachant que je veux que les sources des requêtes soient regroupées.

    D'avance merci de vos remarques et suggestions.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 429
    Points : 24 794
    Points
    24 794
    Par défaut
    C'est une excellente question !

    Je crois avoir un peu tout vu dans les 6 boites que j'ai traversé !

    1. La méthode classique, comme toi, des procédures contenant le SQL avec toute la logique métier dans les TForm, c'est bien pour débuter, ce n'est pas très élégant, très loin des concepts POO et Design Patterns. Le DB Controls et DB Components amènent souvent a cette solution de facilité.
      Le plus gros problème c'est que l'on a éparpillé l'intelligence de l'application un peu partout, difficile de réutiliser des éléments dépendant d'un TForm, une modification du modèle et tous les SQL sont à refaire ! Pas viable pour une application qui aura une longue durée de vie et aura des évolutions permanentes !
      Tu sembles d'ailleurs avoir vu tous ces défauts et tu voudrais les éliminer !
    2. La méthode classique évoluée, des objets métiers contenant le SQL en veillant à une séparation Métier \ Présentation, bannir tous SQL des TForm au profit d'objet réutilisable dans toute circonstance, ne pas hésiter à faire plusieurs objets pour séparer les traitements standards des traitements spécifiques ou des traitements atypiques en jouant avec l'héritage, le polymorphisme, les Factory pour utiliser l'objet le plus adapté, bannir tout accès direct à la Base de donnée qui peuvent poser problème en cas d'évolution majeure faisant évoluer le modèle !
      Je pense que nous sommes beaucoup à développer en cycle spirale ou en cascade modifiée ou comme on dirait maintenant de façon élégamment déguisé par l'Extreme Programming c'est à dire en "Itération" !
      Le cycle en V étant une utopie parfaite pour les SSII qui font des développements dont la pérennité et l'évolutivité n'ont aucun intérêt, mieux vaut tout refaire tous les 4 ans à chaque fois dans un langage différent et des systèmes d'interopérabilité, ça fait vendre de la chair à canon !
    3. La méthode DB avec des Procédures Stockées ou alors une table contenant tous les SQL, plus quelques SQL systèmes en dur dans le code, toujours une couche objet gérant l'appel des PS !
      L'avantage c'est que le déploiement reste sur le serveur !
      les PS faut aimer ça
      le SQL en table, implique de grand VARCHAR ou des BLOBS, faut aimer ça aussi !
      un TClientDataSet pour conserver un cache, pourquoi pas, mais un Locate sur un TClientDataSet contenant des milliers de SQL, est-il aussi performant qu'un SELECT ?
      les optimisations de FireBird sont telles que même en réseau, le cache n'est pas forcément plus rapide, cela se joue à quelques µs !
    4. La méthode externe, avec un stockage des requêtes en XML ou fichier INI, plusieurs fonctions pouvant partager le même SQL, il faut donc faire gaffe, vaut-il mieux avoir des doublons ou fusionner au risque de régression si l'on ne prend pas garde a toutes les utilisations ?
      Comme tu le fait remarquer, le problème de déploiement, soit une installation locale poste par poste, pénible, coûteuse (ou rentable si l'on vend du service)
      Rien n'empêche de stocker en mémoire comme tu le dit les SQL, je maintiens un progiciel utilisant des INI, on a je crois 20 fichiers pour un total de 1Mo de SQL, surement des tas de requête obsolète qui traine !
      Tu peux aussi prévoir un système de versionning intégré à ton application, au début du Ini, tu as numéro de version du logiciel, tu interroges la DB par exemple pour savoir la version en cours, si en local c'est inférieure, tu télécharges une nouvelle version du XML de SQL
      le TClientDataSet peut-être alimenté par un XML d'ailleurs ! Je pense qu'il est plus performant que le TXMLDocument pour la recherche de SQL par leur nom (surtout si l'on a défini des Index)
    5. La méthode RTTI, quasiment pas de SQL en dur mais générer à la volée (on peut d'ailleurs gérer un cache des SQL aussi) par une couche d'Objet Persistant comme Bold, InstantObjects, j'ai en même codé une en Delphi et une autre en C++Builder
      C'est fun à développer, un peu lourd peut-être, il faut aimer l'objet !
      Après on peut coder de façon à faire une sorte de LinQ ou un peu comme le Zend_DB_Select qui fonctionne sur le principe de décorateur pour la description et la génération du SQL
      On écrit plus du SQL, mais on le décrit dans le code, ainsi on peut changer de DB, il suffit de changer la classe chargée de la génération du SQL pour s'adapter au particularité de chaque SGBD mais aussi de la bibliothèque utilisée !


    Les méthodes 3 et 4 posent le problème que l'on fini par dupliquer les PS et SQL, on fini par avoir du code inutile, conserver au cas où ... on m'a parlé de dérive dans les grosses sociétés abusant de SSII appliquant des méthodes de développement très bureaucratique engendrant des horreurs comme des procédures stockées de 10000 lignes gérant du spécifique selon version\client, et qu'en plus il y avait 20000 PS, va donc administrer tout ça !
    Solution : une armée de 100 développeurs !

    Les méthodes 3, 4 et 5 peuvent d'ailleurs est couplé à la méthode 2, le plus important étant de séparation Données \ Métier et Présentation, avoir une couche Objet faisant l'intermédiaire entre les TForm et le TDataSet !
    La séparation complique souvent l'utilisation des DB Controls, il faut savoir être assez souple pour ne pas se priver de cela !
    Voir les LiveBindings, cela pourrait être une approche intéressant pour l'interaction IHM - Objet Métier !


    Voir les sujets :

    Comment utiliser les composants de données et faire de la programmation orientée objet
    [BDD] Séparation de couche de données

    La Question n'est pas tant le stockage des SQL mais surtout comment les réutiliser, les harmoniser, les normaliser ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    566
    Détails du profil
    Informations personnelles :
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2009
    Messages : 566
    Points : 1 045
    Points
    1 045
    Par défaut
    Bonjour,

    Pour une réponse, c'est une réponse.

    Je te remercie pour toutes ces explications, il me faut maintenant un peu de temps pour digérer tout cela.

    Dès que j'aurai défini l'approche que j'envisage de retenir, je reviendrai avec mes questions si nécessaire.

    En fait, il existe une multitude de possibilités avec des avantages et des inconvénients.

    Actuellement, j'utilise pour la lecture de nombreuses vues, mais pour les PS c'est plus rare, je retiens souvent une requête paramétrée.

    Je regarde tout cela et encore merci pour cette réponse complète.

    Si d'autres intervenants ont des expériences personnelles, je suis preneur.

    A+

  4. #4
    Membre confirmé
    Avatar de alheuredudejeuner
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Août 2005
    Messages : 376
    Points : 632
    Points
    632
    Billets dans le blog
    4
    Par défaut J'ai ce souci
    bonjour

    je pensais créer un fichier .pas qui contiendrais une centaines de requêtes, bien classé bien rangées bien ordonnées.

    Ce post me donne matière à réflexion.

    Cordialement

    André

Discussions similaires

  1. [2.x] Où placer les requêtes SQL (sans utiliser d'ORM)
    Par xhion dans le forum Symfony
    Réponses: 6
    Dernier message: 20/12/2012, 10h51
  2. Ne pas placer le nom de la BD devant les tables SQL
    Par fl0w1983 dans le forum Excel
    Réponses: 3
    Dernier message: 19/09/2008, 15h29
  3. [TOMCAT][XML] Ou placer les fichiers XML ?
    Par kitov dans le forum Tomcat et TomEE
    Réponses: 5
    Dernier message: 01/06/2004, 15h29
  4. Comment regrouper les 3requêtes SQL?
    Par SkyDev dans le forum Langage SQL
    Réponses: 16
    Dernier message: 06/03/2004, 14h02
  5. [VB6] Comment lister les serveurs SQL d'un domaine ?
    Par WOLO Laurent dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 29/01/2004, 09h49

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