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++Builder Discussion :

les composants ADO


Sujet :

C++Builder

  1. #1
    Membre régulier
    Inscrit en
    Avril 2008
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 335
    Points : 93
    Points
    93
    Par défaut les composants ADO
    bonjour tout le monde
    pour la première fois je veut utiliser les composant ADO pour interroger ma base de données access via c++ builder.
    j'explique un peut mon code:

    j'ai deux base de données: la première contient les paramètres et le chemin de ma base de données qui contient mes données. le deuxième contient mes données.
    pour cela j'ai crée deux ADOConnection dans DataModule. voici le code:
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    AnsiString Chemin1,Chemin2;
    AnsiString cheminBD1="C:\\Options.mdb";
     
     
          if(FileExists(cheminBD1))
     
                {
                  DataModule1->ADOConnection1->Close();
                     Chemin1 ="Provider=Microsoft.Jet.OLEDB.4.0;"
            "Data Source= "+ cheminBD1+";"+
            "User Id=admin;Password=;";
     
     DataModule1->ADOConnection1->LoginPrompt=false;
     DataModule1->ADOConnection1->ConnectionString =Chemin1;
    DataModule1->ADOConnection1->Open();
     
                     DataModule1->Param->Open();
                     DataModule1->Param->First();
                     AnsiString cheminBD2 =DataModule1->Param->FieldByName("Libellé")->AsString+DataModule1->Param->FieldByName("Libellé1")->AsString;
                     DataModule1->ADOConnection2->Close();
                      Chemin2 ="Provider=Microsoft.Jet.OLEDB.4.0;"
            "Data Source= "+ cheminBD2+";"+
            "User Id=admin;Password=;";
     
     DataModule1->ADOConnection2->LoginPrompt=false;
     DataModule1->ADOConnection2->ConnectionString = Chemin2 ;
     DataModule1->ADOConnection2->Open();
      DataModule1->Query1->Open();
                    //  Edit2->Text=Chemin;
     
     
                }
     
                else
        {
     
         int rep=MessageBox(Handle,"Base de données introuvable","logiciel",MB_ICONSTOP ) ;
     
        }
    j'ai ulilisée ce code a l'entré de l'application il fonctionne mais il prend du temps pour que la fenêtre apparaitre (je pense qu'il dépend de volume de la BDD)
    comment je peut régler ce problème, merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 453
    Points : 24 864
    Points
    24 864
    Par défaut
    La fenêtre lente à survenir est-ce MessageBox ?
    Si oui, c'est donc le FileExists qui est lent ? un anti-virus ?
    Pense que des fichiers à la racine du C: en Seven\Vista, c'est très mal vu (l'UAC peut en refuser l'accès)

    Si non, quelle fenêtre ? une autre dont on a pas le code créé APRES l'ouverture du DataModule
    Si ta DB est sur le réseau Query1->Open(); va charger la tableau en mémoire, donc la lire, donc consommer temps et RAM
    Evidemment plus la table est grosse plus cela sera lent !
    Si ta DB est locale, il est possible que cela soit le même comportement, un TADOTable pour y remédier

    le TADOTable pour ADO\ACCESS doit fournir un équivalent du TTable BDE\Paradox qui gérait la table comme un fichier sans charger le contenu en mémoire (avec un NetDir bien configuré).
    Faudrait le vérifier, je n'ai utilisé ADO mais avec ORACLE qu'une seule fois et tout en TADOQuery à part quelques tables systèmes minuscules !
    Cela doit dépendre du Driver !
    ACCESS je n'ai jamais expérimenté, je suppose que c'est un mode Fichier vu qu'il n'y a pas de serveur !

    le TQuery avait le même problème de lenteur, il créait un fichier temporaire dans le WorkDir contenant le résultat issu SQL puis le chargeait mais ça c'est le problème du SQL en général qui charge le recordset obtenu (il y a des techniques d'optimisation en DBExpress à ce sujet)

    Ton code est très mal indenté, cela complique notre lecture !
    Comme tu as fait un FileExists pour la base locale, tu aurais pu faire de même pour la 2eme ?

    Libellé contient le Chemin genre \\Server\Dossier\Dossier\
    Libellé1 contient le Nom du Fichier
    Il ne manquerait pas un \ entre les deux ? utilise IncludeTrailingPathDelimiter

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
      AnsiString Chemin1,Chemin2;
      AnsiString cheminBD1="C:\\Options.mdb";
     
     
      if(FileExists(cheminBD1))
      {
        DataModule1->ADOConnection1->Close();
        Chemin1 ="Provider=Microsoft.Jet.OLEDB.4.0;"
           "Data Source= "+ cheminBD1+";"+
           "User Id=admin;Password=;";
     
        DataModule1->ADOConnection1->LoginPrompt=false;
        DataModule1->ADOConnection1->ConnectionString =Chemin1;
        DataModule1->ADOConnection1->Open();
     
        DataModule1->Param->Open();
        DataModule1->Param->First();
     
        AnsiString cheminBD2 = 
          IncludeTrailingPathDelimiter(DataModule1->Param->FieldByName("Libellé")->AsString)
          + DataModule1->Param->FieldByName("Libellé1")->AsString;
     
        if(FileExists(cheminBD2))
        {
          DataModule1->ADOConnection2->Close();
          Chemin2 ="Provider=Microsoft.Jet.OLEDB.4.0;"
             "Data Source= "+ cheminBD2+";"+
             "User Id=admin;Password=;";
     
          DataModule1->ADOConnection2->LoginPrompt=false;
          DataModule1->ADOConnection2->ConnectionString = Chemin2 ;
          DataModule1->ADOConnection2->Open();
          DataModule1->Query1->Open();
          ...
        }
        else
          MessageBox(Handle, "Base de données introuvable", "logiciel", MB_ICONSTOP);
      } 
      else
        MessageBox(Handle, "Options introuvables", "logiciel", MB_ICONSTOP);
    MessageBox, tu es comme mes collègues, il préfère (par méconnaissance) cette forme archaïque utilisant du char* ou wchar_t* à la Dialogs.MessageDlg qui évite de se prendre la tête !
    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 régulier
    Inscrit en
    Avril 2008
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 335
    Points : 93
    Points
    93
    Par défaut
    merci ShaiLeTroll pour ta réponse

    je suis sous XP et ma BDD est locale, la fenêtre n'est pas MessageBox, (contient les données de la table)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    quelle fenêtre ? une autre dont on a pas le code créé APRÈS l'ouverture du DataModule
    j'ai constatée que la lenteur de la fenêtre dépendre de la taille de la table
    est ce qu'il y a un moyen de régler ce probleme

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 453
    Points : 24 864
    Points
    24 864
    Par défaut
    Tu as un peu lu ma réponse ou tu t'es arrêté à la ligne 4 ?

    As-tu tenté un TADOTable au lieu d'un TADOQuery ?
    Si je te propose des pistes c'est pour que tu les essayes et que tu fasses un retour dessus !

    Si cela ne résoud pas le problème, c'est surement lié à ADO qui même en mode Table sur ACCESS copie l'ensemble des données dans le RecordSet contrairement au BDE\Paradox

    Citation Envoyé par faniette Voir le message
    j'ai constatée que la lenteur de la fenêtre dépendre de la taille de la table
    Comme je l'ai déjà écrit :

    Citation Envoyé par ShaiLeTroll Voir le message
    Query1->Open(); va charger la tableau en mémoire, donc la lire, donc consommer temps et RAM
    Evidemment plus la table est grosse plus cela sera lent !
    Pourquoi parles-tu de la lenteur de la fenêtre ???
    As-tu mesuré les temps de chaque tache avec un QueryPerformanceCounter pour chercher l'élément lent au lieu de figer sur l'apparition d'une fenêtre !
    Tu vois la conséquence mais pas pleinement la cause !
    Soit plus précise dans ton analyse !

    C'est le Open qui prend du temps car il fait une copie en mémoire des données

    Après, si ta fenêtre contient une Grille
    Si TDBGrid, c'est instantané
    Si TStringGrid, cela recopie encore

    Ouvrir une Table entièrement au démarrage de l'application est une mauvaise pratique !
    Mieux vaut récupérer juste le ou les enregistrements nécessaires au moment utile !
    Quel est le besoin ?
    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

  5. #5
    Membre régulier
    Inscrit en
    Avril 2008
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 335
    Points : 93
    Points
    93
    Par défaut
    bonjour
    merci SaileTroll
    avec TADOTable j'ai pas ce problème, et je mesure pas le temps de chaque tache, en effet ce qui me dérange quand je lance une fenêtre qu'elle contient les informations de ADOQuery dans DBGrid, elle prend de temps pour quelle s'affiche.
    Query1->Open(); va charger la tableau en mémoire, donc la lire, donc consommer temps et RAM
    Evidemment plus la table est grosse plus cela sera lent !
    alors je peut rien faire.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 453
    Points : 24 864
    Points
    24 864
    Par défaut
    Avec le TADOQuery, non il n'y a pas de solution, il faut faire de SQL qui renvoie un jeu limité d'enregistrements c'est le problème de tout mode SQL !

    Tu utilises ACCESS, ce n'est pas un vrai SGBD, conserve le TADOTable si celui est performant !
    Réserve le TADOQuery pour des stats comme COUNT, SUM ou pour récupérer sur des enregisrements avec un WHERE sur PrimaryKey ou ForeignKey

    Pense que l'on peut aussi limiter le nombre d'enregistrement, je ne connais pas ce que propose ACCESS,
    MySQL, il y a LIMIT,
    SQL Server, c'est TOP
    Utilise pour un outil de recherche, récupérer les 100 premiers par exemple (avec certains SGBD, tu peux récupérer les 100 premiers mais avec le nombre réel d'enregistrement disponible)
    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

  7. #7
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Hello
    on peut améliorer notament la perfrormance en utilisant un composant TAdoQuery en menttant la propriété Prepared de ce composant à True avantg de procéder à l'appel de ma méthode Open



    ci-dessous un code d'exemple qui dans le contructeur d'une fiche initialise le contenu d'une combobox avec le contenu d'une Table

    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
     
    TADOQuery *ADOQuery= new TADOQuery(NULL);
      ADOQuery->Connection=Dm->ADOConnection1;  // Dm est mon dataModule
      ADOQuery->SQL->Add("Select * from tbUser");
      ADOQuery->Prepared=true;
      ADOQuery->Active=true; // ou ADOQuery->Open();
      if(ADOQuery->RecordCount)
      {
        while (!ADOQuery->Eof)
        {
          ComboBox1->Items->Add(ADOQuery->Fields->Fields[1]->AsString);
          ADOQuery->Next();
        }
      }
      ComboBox1->Sorted=true;
      delete  ADOQuery;
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 453
    Points : 24 864
    Points
    24 864
    Par défaut
    @DjmSoftware, Prepared n'est utile qu'avec des Paramètres, ton exemple est incomplet !

    Si Prepared a la valeur True et si le composant ensemble de données est connecté à un stockage de données, ADO prépare la commande avant de l'exécuter. Cela implique de conserver la partie paramètres de la commande de requête dans un tampon distinct pour un accès ultérieur plus rapide, en évitant l'insertion à chaque fois des paramètres de la requête dans la commande.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    TADOQuery *ADOQuery= new TADOQuery(NULL);
      ADOQuery->Connection=Dm->ADOConnection1;  // Dm est mon dataModule
      ADOQuery->Text = "Select * from tbUser WHERE UserLogin = :pUserLogin";
      ADOQuery->Prepared := true;
     
      ADOQuery->Parameters->ParamByName('pUserLogin')->AsString := EditLogin->Text;
      ADOQuery->Active=true; // ou ADOQuery->Open();
      ...
    @faniette, quelle volumétrie, évite de récupérer plus de 10000 enregistrements par un TADOQuery
    Après, j'ignore les performances d'ACCESS, je suppose que même 10000 c'est déjà trop, faut peut-être se limiter à 1000
    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

Discussions similaires

  1. Réponses: 1
    Dernier message: 31/07/2008, 10h42
  2. Requête SQL via les composants ADO sur une Table Access 97
    Par Didier100 dans le forum Bases de données
    Réponses: 9
    Dernier message: 21/12/2007, 14h43
  3. Problème avec les composants ADO
    Par elikplim dans le forum Bases de données
    Réponses: 3
    Dernier message: 31/10/2007, 11h39
  4. les composants ado svp ( delphi6 )
    Par Nadirov dans le forum Delphi
    Réponses: 2
    Dernier message: 14/08/2006, 21h08
  5. Problème Update Base de données avec les composants ADO
    Par lingli dans le forum Bases de données
    Réponses: 5
    Dernier message: 20/04/2006, 00h41

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