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

Lazarus Pascal Discussion :

[0.9.29] Fetch partiel avec Dbgrid ?


Sujet :

Lazarus Pascal

  1. #1
    Invité
    Invité(e)
    Par défaut [0.9.29] Fetch partiel avec Dbgrid ?
    Bonjour,

    Est-il possible de faire une espèce de "Fetch partiel" avec une DbGrid ?

    J'ai une table mySQL (distante) importante aussi bien en nombre d'enregistrements qu'en longueur de chaque enregistrement... Dans 90% des cas, l'utilisateur a besoin de la (des) dernière(s) modification(s) sur les enregistrements... (un peu comme le forum).

    Si j'utilise une chaine Dataset --> DbGrid habituelle, le temps de latence entre l'émission de la requête et l'affichage dans la dbGrid est très important... car je ne peux pas me limiter à une portion de la table (il reste les 10% qui veulent engager des opérations sur plus d'enregistrements). J'ai cherché une méthode pour dispenser les 90% du temps de latence sans évidemment pénaliser les 10% qui ont besoin d'une table complète (et pour qui évidemment il faudra patienter dans tous les cas).

    Pour l'instant, mon meilleur (et seul) résultat est l'utilisation de 2 (z)Query et 2 StringGrids (dont une invisible)... La première affiche quasi-instantanément les 100 premiers enregistrements. La seconde charge le "reste" en tâche de fond (multi-thread). Tant que le travail de la seconde n'est pas terminé, les filtres et tris sont bloqués sur la première StringGrid. "Dès" que la seconde est remplie, elle complète la première et les filtres et tris sont débloqués... C'est lourd au niveau programmation (pas tellement le thread) mais les StringGrids à la place des dbGrids ... mais je n'ai trouvé que cette méthode...

    ...car j'ai essayé initialement la même méthode avec 2 dbGrids (donc 2 datasets) superposables. L'idée était la même : 1ère dbGrid immédiatement active et visible tant que 2nde pas "complètement" remplie... puis 2nde visible et 1ère invisible et désactivée après resynchro des sélections... Mais pour une raison que je crois comprendre maintenant, la 2ème chaine dataset-->Dbgrid (qui elle charge toute la table) bloque l'affichage de la première (ou toute autre activité)... J'obtiens finalement la même "ergonomie" (ie non pseudo-parallèle) que si j'utilise classiquement un seul dataset-->dbgrid. En échec, j'ai donc laissé tomber l'histoire des 2 dbgrids avec chacune son propre dataset.... et testé avec 2 StringGrids pour identifier le problème. En réalité, il n'y a pas de "problème" sauf conceptuel de ma part et je doute maintenant que cela puisse fonctionner ainsi (ie avec les 2 dbGrids) : avec la chaine zQuery-->DbGrid, l'utilisation des threads n'est pas adaptée du fait que le zQuery reste "en prise constante" (et que donc son travail ne se termine "jamais") sur la dbGrid et sur la table... donc il reste en quelque sorte "définitivement parallèle" ... alors que dans le cas zQuery+StringGrid, le zQuery effectue son travail de chargement puis se ferme... comme le thread qui a ainsi fait (parallèlement) son travail de mise à jour... On revient alors à la "séquence principale"...

    Mais je me disais que je passais peut-être quand même à côté de quelque chose. En dehors du multi-threading, serait-il possible d'avoir le même "rendu" avec une seule dbGrid ? Sans trop y croire toutefois : il faut 2 requêtes différenciées pour obtenir 2 résultats du serveur... Un immédiat et l'autre qui nécessitera plus de temps... Et une dbGrid ne peut-être associée à ma connaissance qu'à un seul dataset de manière active...

    Petite précision importante quand même : mes dbGrids sont systématiquement en 'ReadOnly', remplies par un DataSet (zQueryDbGrid) réservé à cet effet; Les Insert, Update, Duplicate, Delete et même SELECT LIMIT1 se font par un autre Dataset (zQuerySUID).

    Merci.
    Cordialement. Gilles
    Dernière modification par Invité ; 04/12/2010 à 12h40. Motif: Ajout de précisions et amélioration de la cogitation

  2. #2
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Si tu utilisais LIMIT dans ta requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT * FROM MaTable
    LIMIT 0,100
    Permet de récupérer les 100 premiers éléments de la table
    LIMIT a,b
    a est l'indice (base 0) du premier enregistrement et b le nombre d'enregistements à afficher.
    Ensuite il suffit de gérer les évènements du DBGrid (ou ajouter les boutons qui vont bien) pour afficher le reste.
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Merci de votre réponse.

    Avec le Dataset de la DbGrid, j'effectue votre requête. Elle affiche instantanément les 100 premiers enregistrements. OK.

    Mais la suite de l'affichage de la table ? Comment continue-t-on le remplissage en laissant active la dbGrid et ses 100 premiers enregistrements ? Pas avec une nouvelle requête dans le Dataset de la DbGrid : la réinitialisation du Query entraine celle de la DbGrid (qui se vide) puis le chargement [toujours aussi long des autres enregistrements] vous oblige à patienter (la DbGrid est "gelée")... Autant dans ce cas charger la DbGrid d'un seul coût. Ergonomiquement le résultat est le même...

    Cordialement. Gilles

  4. #4
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Pour afficher la suite il suffit de relancer la requête mais en changeant le paramètre a:
    Exemple
    Ma requête est définie comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT * FROM MaTable
    LIMIT :NumEnr,100
    Un bouton page suivante sur la fiche permet de visualiser les 100 suivantes. De cette manière.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ///MonIndex est une variable globale
    procedure MaForm.OnBoutonSuivantClick(Sender...);
     begin
      Query.Close; 
      MonIndex:=MonIndex+100;
      Query.ParamByName('NumEnr').AsInteger:=MonIndex;
      Query.Open;
     end;
    Ca doit normalement suffire. Si on veut du recouvrement on peu n'incrémenter la variable que de 10 par exemple.
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Si je comprends bien, ce que vous me proposez semble être une pagination... Ce n'est pas ce que je cherche :

    Voici ce qui se passe avec les StringGrids StringGrid1 Tjs Visible, StringGrid2 jamais :

    Première requête dans Zquery1
    Select * FROM database LIMIT 0,100;
    Chargement dans la StringGrid1.
    Fermeture du ZQuery

    { A partir d'ici les 100 premiers enregistrements sont utilisables. La StringGrid1 n'accepte pas les recherches ni les tris}

    Ouverture d'un Thread Parallèle
    Deuxième requête dans zQuery2
    Select * FROM database;
    Chargement de la StringGrid2
    Fermeture du Zquery2
    Complémentation de la StringGrid1 par la StringGrid2
    Champ de recherche activé dans StringGrid1
    Tris activés dans StringGrid1Fermeture du Thread

    Pendant tout le thread, l'utilisateur peut consulter, modifier voire éventuellement détruire un des 100 enregistrements (avec zQuery1 réutilisable après la lecture des 100, le zQuery2 étant utilisé par le thread).

    Je ne comprends pas comment la méthode proposée permet de réaliser cela.

    Concrètement voici mon problème : J'ai une table de 6000 enregistrements sur un serveur mySQL hébergé...
    Dans 90% des cas, l'utilisateur a besoin disons des 10 derniers enregistrements modifiés. Dans 10% des cas, il fera un travail de recherche ou de tris sur les 6000 enregistrements. Je voudrais simplement éviter un temps d'attente inutile de 3 à 4 secondes à 90% des utilisateurs ou dans 90% des cas.

    Avec les StringGrids, je sais faire. Mais c'est lourd. Cela a d'ailleurs été d'autant plus lourd que les StringGrids étaient buguées au niveau des colonnes invisibles (Il faut au moins cacher les ID). Voila pourquoi je suis toujours très "sensible" au problème des StringGrids que j'estimais inutilisables (pour moi) jusqu'à la 0.9.29.

    Avec les dbGrids je ne pense pas que cela soit "conceptuellement" possible ne serait-ce que par le fait que l'association dataset--dbgrid n'a pour limite "dans le temps" que l'action de fermeture du Dataset (car la chaine dataset--dbgrid boucle sur elle-même en permanence)... donc le thread parallèle ne peut se "resynchroniser" à l'évènement principal qu'à la fermeture du dataset... ce qui rend à ce moment là, la dbgrid inutilisable. La différence en StringGrid, c'est que le dataset à l'issue du remplissage s'arrête. Désolé, mais je ne trouve pas de vocabulaire adapté pour décrire mieux le problème. Donc je voulais que l'on me confirme cette analyse.

    D'un autre côté, je me demandais s'il n'y avait pas une autre méthode. Il m'a fallu implanter de nombreuses fonctions sur les StringGrids : Sélection de lignes non contigües, insertion de flèches et de champs de recherche dans les entêtes, recherche sur plusieurs colonnes (avec des combinaisons de Asc et de Desc)... y compris les valeurs numériques sous toutes leurs formes (entières, décimales, négatives, positives...), calcul de la largeur de la dernière colonne pour compléter les lignes de bord à bord (qui dans certaines circonstances fonctionnent mal en mode "auto")... J'ai fait cela en 0.9.28 et je peste encore avec la 0.9.29 qui est "partie" sur des bases différentes pour enfin gérer proprement les colonnes invisibles... J'avais d'ailleurs alors demander de l'aide pour regrouper tous ces codes additionnels dans un composant, mon niveau "composants" de l'époque ne me permettant pas de faire cela seul. J'y arriverai peut-être maintenant... Grâce à l'aide de certains membres de ce forum, j'ai fait quelques progrès en la matière mais je ne sais pas vraiment s'ils seraient suffisants. De toute façon, je n'ai plus le temps. Bref, s'il y avait une méthode autre que celle faisant appel aux StringGrids, malgré le travail déjà réalisé, je serais preneur

    Cordialement. Gilles.
    Dernière modification par Invité ; 10/12/2010 à 16h44.

  6. #6
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Je comprends le problème si
    Dans 90% des cas, l'utilisateur a besoin disons des 10 derniers enregistrements modifiés.
    dans ce cas là pourquoi ne pas ajouter dans la table un champs du type TIMESTAMP qui donne la date de la dernière modification. Ensuite il suffit de trier sur ce champs.

    Moi non plus je ne crois pas qu'il soit possible de faire ça avec un DBGrid. Par contre il faut voir s'il n'est pas possible d'utiliser des procédures stockées mais je ne vois pas trop comment. Sinon la solution avec les threads et stringgrid me semble bonne mais lourde. Une autre solution peut être une Listbox en utilisant l'évènement OnwerDraw.
    Ceci dit si le délais d'attente n'est que de quelques secondes ce n'est pas forcément très génant (j'attends bien mon train quelque minutes moi tous les matins ).
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Oui c'est le tri que j'adopte, pas avec réellement un datestamp mais un champ basé sur un datestamp (avec une partie aléatoire) car en réseau à partir du moment où on se déconnecte de la base (dans le StringGrid par exemple), ce type de clé (unique) permet de savoir instantanément s'il faut rafraîchir la ligne ou si le champ a été modifié par un autre utilisateur depuis son SELECT avant d'engager un UPDATE.

    Pour la perception de l'attente... On peut patienter : oui et non... Pour l'utilisation d'un Dataset sur une Form avec une table lourde, il faut déjà contourner le "léger" problème de l'affichage de la Form... Par défaut, la Form s'affiche que quand la requête est terminée... Ce qui laisse penser à une panne (si on place l'évènement dans onCreate par exemple). Dans onShow ce n'est guère mieux... Après quelques manipulations on peut améliorer la chose : Apparition immédiate de la Form, d'un dbGrid vierge et d'un label clignotant "Chargement en cours"... puis à la fin de la charge de la table... activation de la dbGrid...

    Merci pour votre aide.

    Bon WE. Cordialement. Gilles
    Dernière modification par Invité ; 11/12/2010 à 11h33.

  8. #8
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par selzig Voir le message
    Bonjour,

    Pour la perception de l'attente... On peut patienter : oui et non... Pour l'utilisation d'un Dataset sur une Form avec une table lourde, il faut déjà contourner le "léger" problème de l'affichage de la Form... Par défaut, la Form s'affiche que quand la requête est terminée... Ce qui laisse penser à une panne (si on place l'évènement dans onCreate par exemple). Dans onShow ce n'est guère mieux... Après quelques manipulations on peut améliorer la chose : Apparition immédiate de la Form, d'un dbGrid vierge et d'un label clignotant "Chargement en cours"... puis à la fin de la charge de la table... activation de la dbGrid...
    Oui c'est vrai il faut montrer que ça tourne. Dans ce cas je met une boite de dialogue avec un truc qui bouge et je lance un thread qui fait le travail. Une fois le travail terminé la boite disparait.
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  9. #9
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Je viens de penser à une solution en prenant mon petit déjeuner (comme quoi les idées ça vient comme ça vient).

    Pourquoi ne pas faire une vue. Je m'explique au lieu de remplir le DBGrid avec 6000 entrées il serait peut être mieux de créer dans la bese une vue. Ensuite cette vue est accessible comme une table normale et donc le fetch partiel est plus simple.
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  10. #10
    Membre expérimenté
    Avatar de chris37
    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Juillet 2007
    Messages
    378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France

    Informations professionnelles :
    Activité : Directeur des systèmes d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 378
    Points : 1 688
    Points
    1 688
    Par défaut
    Hello,

    Allez, je m'y met aussi

    Effectivement, la proposition de Remi est une bonne piste.

    Ici, à la boite j'ai des tables de plus de 50000 enreg et l'ensemble des affichages se fait uniquement avec des tables mémoires MAIS, en aucun ca je monte 6000 enreg ! 500 Maxi en fonction de critères de sélections définis Et le tout piloté par des vues permetant de ne pas s'encombrer des jointures dans le programmes (Les vues sont faites pour ça).

    L'utilisateur ne scroll jamais une table de 6000 lignes ! (Surtout sur de l'accès distant)

    Gilles, ton analyse doit être repensée si tu veux mon avis....

    Cordialement,
    Chris

  11. #11
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    @Chris... pas nécessairement. Imagine que je veuille laisser se balader la personne à son gré sur 6000 références d'un catalogue... ou que je veuille lui laisser la possibilité d'utiliser des procédures de tris adaptatives où la convergence vers le résultat s'effectue notamment par la visualisation des enregistrements qui n'appartiennent pas au filtre. Dans ces 2 cas, pourquoi est-ce que je brimerais sa navigation en filtrant pour lui la base brute ? Parce que je ne sais pas faire... autrement ? Si, si avec les StringGrids... Même si elles ne sont toujours pas exemptes de bugs au niveau de la "couche Columns", elles sont exploitables. Mais je ne crois pas que le code de base reste stable suffisamment longtemps (car encore conceptuellement bizarre notamment sur leur numérotation) pour envisager de faire un composant "amélioré" avec...

    D'un autre côté, comme je l'ai écrit, j'utilise 2 Queries, un pour afficher la dbGrid [ReadOnly], l'autre pour modifier les enregistrements. En cas d'erreur d'intégrité dans un UPDATE ou un INSERT , la dbGrid se place sur l'enregistrement qui interdit la modification ou l'insertion du nouvel enregistrement (cf copie d'écran ci-jointe). Quid si l'enregistrement incriminé n'appartient pas au filtre de la dbGrid ? Tu vois, on peut imaginer beaucoup de cas, où finalement l'affichage d'une table complète (de 6000 enregistrements) n'est pas aussi inadapté qu'il n'y parait.

    Le i18n avait qqs probs... mais c'est maintenant résolu.


    @xxxx
    Sinon j'aimerais soumettre une autre idée avec les dbGrids; Je la testerai pendant les prochaines vacances scolaires si je n'ai pas sur le forum de "contre-indication" théorique : Y-a-t-il quelque chose qui prédispose l'approche ci-dessous à l'échec ? En ce moment je n'ai pas trop le temps. C'est le moment des conseils de classe et avant... il a fallu faire des évaluations de synthèse des connaissances acquises pendant le trimestre... et les corriger.

    J'ai constaté la chose suivante [Je prends les composants natifs pour "parler" au plus grand nombre mais il y a la même chose en Zeos avec FetchRow]

    J'ai défini PacketRecords:= 100; J'ouvre le SQLquery1... et évidemment affichage instantané au terme duquel

    procedure TForm1.Datasource1StateChange(Sender: TObject);
    begin
    showmessage(IntToStr(DBGrid1.DataSource.DataSet.RecordCount));
    end;
    -->100

    Si dans le DataSource1StageChange (ou dans un autre pojnt d'accés de la terminaison du chargement de la dbGrid -l'important c'st qu'il y en ait au moins un-*), je lançais un thread parallèle avec
    SQLQuery1.PacketRecords:=9999999999999;**
    SQLQuery1.Refresh;
    puis que je le "ferme" (à voir comment : peut-être avec *). Théoriquement, cela devrait bloquer un très court instant la dbGrid au moment où la bulle "des enregistrements" du datasource va s'afficher de son cache dans le dbGrid... Comme c'est un thread normalement la "lente" action du remplissage du (cache du) datasource par le SQLquery devrait ne pas bloquer le programme. Et avantage de la méthode, on ne "Clear" pas la requête donc on ne décharge pas le dbGrid.

    Un avis d'infaisabilité théorique ?

    Merci. Gilles

    ** Je n'arrive pas à passer SQLQuery1.PacketRecords :=0 (FetchRow := 0 oui) pour indiquer que je ne veux plus de Fetch partiel.
    Dernière modification par Invité ; 13/12/2010 à 10h53.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Donc j'ai regardé de plus près avec des Threads; J'ai abandonné le FetchRow qui charge d'abord intégralement la bulle de données de la base dans le cache... sans qu'on puisse intervenir. Donc aucun intérêt.

    Comme l'a suggéré Gouyon, j'utilise une requête "paramétrée" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    zQuery1.SQL.Clear;
    zQuery1.SQL.Add('SELECT * FROM maTable LIMIT 0, :PeuImporte');
    zquery1.Params[0].AsInteger := 100 ;
    zQuery1.Open;
    que je modifie dynamiquement ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    zquery1.Params[0].AsInteger := 99999 ;
    zQuery1.Refresh;
    En dehors d'un Thread, cela fonctionne sur un ensemble zConnection-->dbGrid. Le seul intérêt (hors d'un Thread) est de constater que l'on peut modifier la requête sans fermer le zQuery donc vider la dbGrid... ce qui présente évidemment une avancée significative puisqu'on peut alors espérer mettre à jour la dbGrid sans fermer le DataSet.

    Sauf que je bloque sur un autre problème.
    Comment thread-on un ensemble zConnection-->zQuery-->Datasource-->DBgrid ?

    Dans un Thread, ceci fonctionne à condition qu'aucun DataSource+DbGrid ne soit branché au zQuery :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Memo1.Clear;
    zQuery1.SQL.Clear;
    zQuery1.SQL.Add('SELECT * FROM maTable LIMIT 0, :PeuImporte');
    zquery1.Params[0].AsInteger := 99999 ;
    zQuery1.Open;
    zQuery1.First;
    While not zQuery1.EOF do begin
        Memo1.Lines.Add(zQuery1ID.AsString);
        zQuery1.Next;
    end;
    C'est avec un code de ce type (sans le LIMIT) que je charge actuellement par Thread la table complète dans la StringGrid invisible pour régler ce problème de latence.

    Mais, si je complète ma chaîne zConnection1+zQuery1 par DataSource1-->DbGrid1 avec le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    zQuery1.SQL.Clear;
    zQuery1.SQL.Add('SELECT * FROM maTable LIMIT 0, :PeuImporte');
    zquery1.Params[0].AsInteger := 99999 ;
    zQuery1.Open;
    J'ai un plantage dont j'ai enfin réussi à obtenir l'erreur :
    ... que je ne comprends pas bien... La synchronisation oblige à repasser par le thread principal et donc le multithread n'a plus d'intérêt c'est donc le datasource qui "oblige" (... ?)

    Petit tour par notre ami Google : Pour l'instant, c'est encore l'obscurité... J'ai trouvé de nombreux articles sur le Multi-threading et les datas mais curieusement ils n'utilisent pas le datasource+dbgrid mais des ListBox ou des Memo pour illustrer le propos; J'en reviens donc à ma précédente question : y a-t-il une incompatibilité entre les datasource+dbGrid et les threads ?

    Merci. Cordialement.
    Gilles
    Dernière modification par Invité ; 18/12/2010 à 18h01.

  13. #13
    Membre expérimenté
    Avatar de chris37
    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Juillet 2007
    Messages
    378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France

    Informations professionnelles :
    Activité : Directeur des systèmes d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 378
    Points : 1 688
    Points
    1 688
    Par défaut
    Bonsoir,

    Par expérience avec Delphi, jamais de gestion d'accès SGBD dans les thread car c'est source à problèmes vu la perte de contexte mémoire.....

    Certains y arrivent peut être mais en tout cas, je le déconseil fortement

    Pour ton soucis Gilles, je persiste et signe dans la proposition de mon dernier poste. A savoir, revoir ton analyse car ma modeste expérience dans la conception d' ERP diverses (20 ans ) mets en évidence un manque d'analyse sur le mode opératoire de ton application....

    On en reparle

    Bon WE
    Cordialement,
    Chris

  14. #14
    Invité
    Invité(e)
    Par défaut
    Bonsoir Chris...

    Ce n'est pas vraiment un soucis, mais plutôt une curiosité. Oui, les habitudes peuvent se changer... et je n'ai rien contre les vues... et je fais tout à fait confiance à ton jugement et à ton expérience sur la question. Mais tu sais bien que je ne suis pas vraiment en production et que j'adore me poser des questions... Et comme le code de Lazarus est ouvert ...

    Les threads et la base de données cela me semble en effet risqué si on systématise leur emploi conjoint. Mais dans le cas précis, c'était pour répondre à un problème de fluidité lors de l'ouverture de la fenêtre compte tenu de l'énoncé que j'avais formulé... On pourrait le rencontrer aussi pour imprimer des volumes importants sans bloquer le programme... Je n'ai pas essayé, j'ai un peu de mal avec lazReport.

    Enfin dans mon "problème", c'est visiblement le DataSource qui bloque... et je suis presque persuadé qu'il ne peut pas être placé dans un "thread". Il fallait déjà identifier le problème. Pendant un temps, je ne me suis pas rendu compte où il était et même qu'il pouvait exister. C'est dommage parce que le DataSet lui peut l'être...

    Et quand même avec les StringGrids, on obtient une "belle" fluidité comparée aux dbGrids sur les volumes importants notamment quand la base est hébergée à distance. Le parallélisme cela a son charme. Et même si elles ne sont pas à mon avis vraiment "fixées" dans Lazarus, et qu'elles présentent encore des difficultés de programmation, elles sont fonctionnelles pour ce que j'essayais d'en faire. Mais évidemment en production, c'est (ce serait) un "enfer" à programmer...

    Je n'ai pas beaucoup trouvé de Doc sur le "thread des datasources". Je vais donc faire encore quelques essais (essayer de voir un peu comment cela fonctionne et probablement abandonner cette voie) au profit de l'amélioration de mes StringGrids : mes codes sont inadaptés à la 0.9.29, torturés qu'ils étaient pour s'adapter à la 0.9.28.

    Encore merci pour tes conseils. Au plaisir de te relire.
    A bientôt. Cordialement.
    Gilles.
    Dernière modification par Invité ; 18/12/2010 à 19h09. Motif: Orthographe

  15. #15
    Membre expérimenté
    Avatar de chris37
    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Juillet 2007
    Messages
    378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France

    Informations professionnelles :
    Activité : Directeur des systèmes d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 378
    Points : 1 688
    Points
    1 688
    Par défaut
    Concernant les StringGrid

    J'utilise principalement Windev pour toutes les applis que je développe mais j'ai commencé la migration de certains modules vers Lazarus. Meme test avec QT

    Analyse identique avec IDE différent.

    Et bien que je fais très facilement avec Windev, je le reproduis sans trop de "Bidouille" depuis Lazarus et les algo de remplissage sont très proches et ils utilisent les mêmes requetes puisque celle ci sont dans des fichiers externes qui sont pilotés par l'application.....(me contacter pour plus d'info). Pas besoin de recompiler en cas de changement.
    L'affichage des colonnes est aussi 100% dynamique et paramétrable.
    Bien sur, je filtre le nombre de lignes maxi pour une meilleure fluidité.

    Toujours à ta dispo mon ami
    Cordialement,
    Chris

  16. #16
    Invité
    Invité(e)
    Par défaut
    Bonjour Chris,

    Windev... hum, j'ai décroché il y a longtemps. J'avais écrit un logiciel interne à mon lycée de gestion de notes en 5.5. Il a fallu le réécrire totalement en 7.5... avec entre deux, une version 7.0 qui était "prématurée".... Oui, je me rappelle un peu des TableSupprime et TableTri... Donc, cela doit être très différent maintenant parce que, à cette époque (Windev 7.5), je l'ai réécrit en Delphi 7 (et Zeos que j'ai conservé en Lazarus - je n'ai pas bien aimé dbExpress)... et très franchement , je n'ai pas vu au niveau programmation de réelles similitudes hormis la BDD et les requêtes SQL utilisées (je n'utilisais pas à l'époque le système maison Hlitpremier...). Ceci dit, ce n'est absolument pas une critique de Windev. Cela m'a semblé -hormis cette péripétie du saut de 5.5 à 7.5- un logiciel tout à fait efficace pour la production... La véritable raison de l'abandon de cette plateforme est mon plaisir inégalé à développer en Pascal, qui plus est, avec un IDE léger et "direct" à la Delphi 7 ou à la Lazarus . C'est sans doute pourquoi je ne suis pas très sensible aux versions suivantes (200x) et complètement hermétique à Delphi Prism... Ce qui ne signifie en aucune manière que ces produits aient un quelconque défaut ou soient improductifs... C'est un simple ressenti personnel, la relation que chacun entretient avec sa plateforme de développement.

    Bref actuellement, la saisie et la gestion des notes peuvent s'effectuer sous Win et Lin avec Lazarus. Seule l'impression des bulletins et synthèses doit être effectuée sous Windows... Je n'ai jamais réussi à percer les secrets de LazReport qui pourtant théoriquement devrait permettre de réaliser l'équivalent... Et j'ai presque terminé l'intégration d'un dictionnaire de vérification orthographique des annotations des enseignant(e)s par Hash... J'ai lu récemment que c'était possible par un simple clic de bouton sur les champs de saisie dans Windev à condition qu'Ooo soit installé sur le poste... Je sais ce que tu vas dire... Chacun ses satisfactions et ses contraintes. Ou l'inverse suivant sa situation du moment.

    Pour en revenir à mon problème, je laisse tomber... Il réside visiblement dans le fait que le couple Datasource-dbGrid est interactif avec "l'extérieur" et demande donc à "sortir" du Thread parallèle où je l'enferme, ce qui nécessite une synchronisation avec le Thread principal (celui du programme) d'où l'erreur signalée.

    Compte tenu de ma pratique des StringGrids, je vais assembler mon code pour réaliser un petit composant dbStringGrid : On y précisera le Dataset (ReadOnly), la requête avec un LIMIT... pour une ouverture en 2 temps. Je vais laisser en "Private" tout ce qui ne sert à "rien" dans mon approche au départ à partir d'un TCustomStringGrid... et accenter mon travail sur la partie de l'Inspecteur d'objet qui permet de définir les colonnes... et dans laquelle, il faut que j'incorpore le "découpage" de la requête pour son asssociation aux colonnes (avec un ersatz de RegEx déjà développé pour un autre projet, -RegEx une carence de Lazarus et jusqu'alors récente de Delphi), la déclaration des tris. C'est ce dernier point qui me semble le plus compliqué (incertain) de prime abord : si tu as le temps, fais un petit tour sur le forum pendant les vacances... Aide requise très probablement. Pour le reste, l'incorporation du Thread de chargement pour le partie longue ne posera pas de prob, je le fais déjà. Le multiselect (sur des lignes non contiguës), les tris sur x colonnes avec des types différents. C'est fait aussi. Y compris la gestion des images signalant les tris actifs dans les entêtes... Bref pour en revenir à ta référence Windevienne : je cherche à "composer" une "table mémoire" respectant le cahier des charges qui a valu l'ouverture de cette discussion.

    Je considère la discussion résolue. Oui, à mon sens, il y a une impossibilité théorique d'encapsuler un Datasource+dbGrid dans un Thread. Mais, il y a une autre solution... qui demande trop de code (de tuyauterie) externe et qui noie actuellement celui de la couche métier dans mes applications. Mais avec les StringGrids actuelles (0.9.29), c'est peut-être jouable.

    Cordialement.
    A bientôt. Gilles.
    Dernière modification par Invité ; 20/12/2010 à 12h53. Motif: Amélioration de la syntaxe

Discussions similaires

  1. Modifier des donnees avec DBGrid ?
    Par msuire dans le forum Bases de données
    Réponses: 2
    Dernier message: 02/12/2006, 00h58
  2. [SQL2K] jointure partielle avec un max
    Par Monstros Velu dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 30/10/2006, 10h14
  3. [XSLT]copie partielle avec condition sur les axes
    Par MasterOfChakhaL dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 13/10/2006, 19h15
  4. Gestion clavier dans une form avec dbgrid
    Par albedo dans le forum C++Builder
    Réponses: 3
    Dernier message: 25/04/2006, 15h42
  5. Problème avec Dbgrid
    Par RBIK dans le forum Bases de données
    Réponses: 4
    Dernier message: 17/06/2004, 14h31

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