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 :

DataSetProvider, ClientDataSet, DataSource, DBGrid et comptage de lignes


Sujet :

Bases de données Delphi

  1. #1
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut DataSetProvider, ClientDataSet, DataSource, DBGrid et comptage de lignes
    Bonjour tout le monde,

    j'affiche les données d'une requête du type SELECT FROM WHERE GROUP BY ORDER BY HAVING.
    Pour cela, j'utilise un TSQLQuery qui possède la requête SQL.
    J'ai un DataSetProvider relié au SQLQuery, puis un ClientDataSet et un DataSource.
    Pour afficher les données, j'utilise un TDBGrid qui est relié au DataSource.
    Lorsque j'active le ClientDataSet, les données s'affichent, pas toutes les données, juste les 200 premières.
    Quand l'utilisateur descend le curseur, les données continuent à s'afficher de façon progressive. C'est très utile lorsqu'on travaille sur des millions d'enregistrement, les temps de réponse restent acceptables.

    J'ai mis un bouton qui lorsqu'on clique dessus donne le nombre total d'enregistrements.
    Pour se faire, je remets le curseur du SQLQuery à First, puis je compte jusqu'à ce qu'il arrive à Eof puis je le remets à First. Enfin j'affiche la valeur comptée.

    Le problème est qu'ensuite, les données sont toutes "marquées" comme lues et quand on descend le curseur dans le DBGrid, on bloque et ne vois plus les données suivantes.

    Si j'essaie d'afficher le RecordCount du SQLQuery, la valeur est fausse car il ne tient pas compte des agrégations de la requête.
    Si j'essaie d'afficher le RecordCount du ClientDataSet, la valeur est fausse car elle ne prend en compte que ce qui a été chargé dans le DBGrid.

    J'ai pensé charger toutes les données dans le DBGrid, mais c'est extrèmement plus lent que la méthode actuelle et quand on travaille sur plusieurs millions d'enregistrement, ce n'est pas exploitable.

    J'ai aussi essayé d'utiliser des Bookmark, mais ça ne fonctionne pas.

    Quelle est la bonne solution pour avoir le nombre d'enregistrements valide et qu'on puisse toujours voir les données suivantes dans le DBGrid ?
    Merci pour votre aide.

  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
    peut-être un peu vilain, mais lors du lancement de la requête, tu lance avant, un "SELECT COUNT FROM WHERE GROUP BY HAVING" ... et tu obtiens ainsi tu nombre de record

    Il me semble que ADO gère en interne des paquets, peut-être que pour certaines parties de l'application, essayer cette autre lib ... je n'ai jamais utilisé ADO pour une telle volumétrie, et en MySQL on a le merveilleux LIMIT ...
    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 confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut,
    j'utilise déjà les composants ADO aussi, mais mon code doit fonctionner avec les composants IBX, DBExpress et ADO.
    Je ne peux pas faire de LIMIT car ça ne fonctionne qu'avec MySQL et le code doit être plus toute base de données.
    De plus, le but n'est pas de filtrer les données mais ne n'afficher que les données au fur et à mesure et avoir le nombre total.

    Faire une requête du type SELECT COUNT(*) FROM WHERE ...., peux poser quelques problèmes, par exemple, quand tu as des champs agrégés dans le SELECT, les champs non agrégés se retrouvent dans le GROUP BY, hors si tous les champs sont agrégés, il n'y a plus aucun champ dans le GROUP BY, du coup la requête SELECT COUNT(*), au lieu de remonter 1 va te donner le nombre de lignes sans agrégation.
    De plus, imagines qu'il y ait 4 champs dans la table, tu fais une requête avec en SELECT le premier champ non agrégé et le second champ agrégé, tu te retrouves juste avec le premier champ dans le GROUP BY.
    Si tu fais un SELECT COUNT(*) FROM TABLE GROUP BY CHAMP1, cette requête ne va pas te remonter qu'une valeur mais attend de valeur distincte dans CHAMP1.
    Donc, c'est pas suffisament sûr.

    De plus, presque tout le code est fini, je me doute que je mélange les pinceaux avec tous ses composants mais c'est faisable d'une façon ou d'une autre mais je ne sais pas encore laquelle.

  4. #4
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par WebPac Voir le message
    J'ai mis un bouton qui lorsqu'on clique dessus donne le nombre total d'enregistrements.
    Pour se faire, je remets le curseur du SQLQuery à First, puis je compte jusqu'à ce qu'il arrive à Eof puis je le remets à First. Enfin j'affiche la valeur comptée.
    Pourquoi tu n'utilse pas la même méthode, mais sur un autre composant SQLQuery ayant la même requête que le premier ?
    Si vous êtes libre, choisissez le Logiciel Libre.

  5. #5
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Vu la volumetrie que tu sembles vouloir traiter, pour moi il n'y a qu'une seule solution qui tienne la route au niveau perf : Celle de ShaiLeTroll, a savoir faire une autre requête pour compter le nombre d'enregistrements. Sinon tu vas devoir charger d'abord toutes lignes pour les compters ensuite dans le client.

    Il n'y a pas de questions à se poser. Si tu remplis la grille avec une requête

    SELECT FROM WHERE GROUP BY ORDER BY HAVING
    Tu comptes les enregistrements que cette requête va retourner avec :

    select count(*) from (SELECT FROM WHERE GROUP BY ORDER BY HAVING) A
    Il suffit d'imbriquer les requêtes, peut importe le contenu de ton select à l'intérieur (bon tu peux enlever l'order by lorsque tu comptes les enregistrements).

  6. #6
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Merci pour vos réponses.
    Franck SORIANO, je ne connaissais pas les requêtes imbriquées dans le FROM, je savais que ça existait dans le WHERE et dans le SELECT mais pas pour toutes les bases de données.
    Est-ce qu'une requête imbriquée dans le FROM est un standard SQL ? Est-ce que ça fonctionne avec toutes les bases de données ?

    TryExceptEnd, si la méthode de Franck SORIANO pose problème avec certaines bases de données, j'utiliserai ta méthode à la place, ou alors, j'essaie d'implémenter les 2 méthodes.

    Merci en tout cas pour vos idées.

  7. #7
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    J'ai testé avec Firebird et Oracle et ça fonctionne.
    J'ai fait un Tty Except et revient à l'ancienne méthode si ça ne fonctionne pas.
    Je mets en [Résolu].

  8. #8
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Est-ce qu'une requête imbriquée dans le FROM est un standard SQL ?
    Pour moi oui. Je crois que ça fait parti du standard SQL (mais je n'en suis pas tout à fait sûr).

    Est-ce que ça fonctionne avec toutes les bases de données ?
    Là j'ai un doute. Certain SGBD sont réputés pour ne pas accepter les requêtes imbriquées.
    Par exemple, il me semble que MySQL ne les gèrent que depuis peu.

    Par contre, ça marche à la perfection avec Oracle et SQL Server. Ce qui est important, c'est de bien mettre l'alias sur le résultat du select à l'intérieur.

  9. #9
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Pour moi oui. Je crois que ça fait parti du standard SQL (mais je n'en suis pas tout à fait sûr).


    Là j'ai un doute. Certain SGBD sont réputés pour ne pas accepter les requêtes imbriquées.
    Par exemple, il me semble que MySQL ne les gèrent que depuis peu.

    Par contre, ça marche à la perfection avec Oracle et SQL Server. Ce qui est important, c'est de bien mettre l'alias sur le résultat du select à l'intérieur.
    Quand tu parles de l'alias sur le résultat du select à l'intérieur, tu parles du A qui traine à la fin de la requête ? Je l'ai pris pour une erreur de frappe.
    Ou tu parles des alias des champs dans la requête imbriquée ? Si c'est le cas, je n'ai pas la main dessus car c'est l'utilisateur qui peut paramétrer le fait que les champs sont aliassés ou pas.
    Normalement, ils aliassent tout le temps, si ça pose parfois problème, je leur dirai d'aliasser.

  10. #10
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Quand tu parles de l'alias sur le résultat du select à l'intérieur, tu parles du A qui traine à la fin de la requête ? Je l'ai pris pour une erreur de frappe.
    Oui, je parle du A à la fin. Pour pas mal de SGBD, tu ne peux faire que le SELECT FROM une table, et pas FROM un autre select. Pour que le SGBD comprenne qu'il doit considérer le Select imbriquer comme une table et donc comme la source du deuxième select, il faut définir un alias au select imbriqué.

    En tout cas, le "A" que j'ai mis à la fin est nécessaire pour SQL Server. Il passe avec Oracle mais je ne sais pas si c'est une nécessité également pour Oracle.

  11. #11
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Bonjour, merci pour ces précisions.
    Sans l'alias ça fonctionne pour Oracle et Firebird (les 2 seules bases que j'ai testé pour l'instant), je vais quand même rajouter l'alias pour avoir plus de chances que ça passe pour les autres bases de données.

  12. #12
    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
    Je réssucite ce sujet, ...

    J'ai une table avec plus de 2 millions d'enregistrement dans une table, le table d'executer la requête est de quelques dizaines de secondes, le temps de l'afficher est négligeable ...

    Avec le jeu DataSetProvider, ClientDataSet, DataSource, DBGrid comment peux-tu demander l'ouverture de la requête, une fois qu'il a les 20 premiers, il s'arrête, et il reprend l'execution avec les 20 suivants lors que l'on fait défiler

    Le TClientDataSet le fait en standard avec PacketRecords, OK
    Mais la requête transmise dans CommandText est executé en entier, hors, je ne voulais que les 20 premiers enreg pour le moment ... en dessous, j'ai un composant ADO ... je voudrais me limiter à cela pour le moment,

    la base de Données est MySQL, le Driver ODBC 3.51 (vieux non ?)
    je pourrais faire un LIMIT (donc programmer mon programmer DataSetProvider) mais d'abord, je voudrais épuiser les possibilités standards ... l'ayant déjà vu chez un de mes employeurs, et n'ayant jamais pu étudier la lib côté serveur à ce sujet, j'ignore qu'elle était l'astuce magique pour ne renvoyer que les 20 premiers enreg sur 2 millions, puis les 21 à 40, ...
    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

  13. #13
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Je ne suis pas expert de cette partie là, c'était un collègue qui l'avait fait à l'époque.
    Mais c'est bien la propriété PacketRecords que tu dois mettre à 20 et qui ne fera que l'application n'importera que les 20 premières lignes.

  14. #14
    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
    Pourtant, cela me lance la requête en entier (la query lié au Provider contient le million d'enreg), j'aimerais qu'il "arrête" la requête dès qu'il a les 20 premiers ... pour gagner du temps (peut-être une question de driver ou d'implémentation provider distant ?)

    si je passe avec les composants CoreLab, je pourrais toujours tenter le mode Asynchrone par exemple ...

    Petite précision, j'ai mis tous les composants dans la même application, je n'ai pas fait de IServerApp ... je pense que dans la lib de mon ancien employeur, il devait y avoir une astuce, cela rendait la main dès que le 20eme enreg était récupéré, et le reste de la requête continuait sa vie en asynchrone, je n'ai jamais vérifié, cela fonctionnait très bien ...

    j'ai mis une valeur dans PacketRecords, j'ai droit à une erreur, au bout du 550 eme enreg ...
    "Une opération en plusieurs étapes a généré des erreurs. Vérifiez chaque valeur d'état." classique d'ADO lorsqu'il a une erreur, j'ai eu pareil avec des dates incorrectes en ORACLE, c'est tellement explicite !

    Je n'ai pas l'erreur en passant via une ADOQuery en direct ... seulement via Provider ...
    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

  15. #15
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut,

    il se peut qu'il y ait malentendu, donc je reprends le cheminement de ce qui est fait (en tout cas dans mon application), la requête est ouverte avec un Open, donc l'application attend que la base de données ouvre la requête entièrement puis lui rende la main.
    Puis, via le PacketRecord, le Dbg ne demande que les premières lignes de la requête, puis s'arrête et ne demande pas de remonter les autres lignes qui sont en attente.
    Mais quoiqu'il arrive, il faut que la requête s'ouvre entièrement.
    C'est comme si on le fait en code avec, .First et .Next, on ne récupère que les premières lignes mais qu'une fois la requête ouverte.

    Je n'utilise pas non plus des IServerApp, je développe des clients lourds et ça fonctionne correctement.
    Je n'utilise pas les composants ADO pour MySQL, j'utilise les composants dbExpress avec connexion native à MySQL et j'utilise la dll dbexpmda.dll de CoreLab, bien moins buguée que celle de Borland et surtout, elle est toujours mise à jour.

  16. #16
    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
    En fait, j'utilise ADO pour tester, si non j'utilise MyDAC de CoreLab, ... et semble avec ce que tu me dit, cela ouvre la requête entier (trop long) alors, alors à moi de faire un provider qui gérerait des Packets implementé avec un LIMIT ...

    Bon dommage, j'ai cru que cela pouvait se faire plus simplement en mélangeant de PacketRecords, MaxRecords, BlockReadSize, ...

    En fait, bien sur, c'est juste un test par curiosité, jamais je n'ouvre une table en entier cela ne sert à rien ... mais certaines de mes requêtes prennent quand même 3-4 secondes et j'aurais aimé faire croire que c'était instantané (pour cela j'avais vu des fonctions asynchrone dans la libMySQL.dll, mais je ne les retrouve plus ... c'est entre, je l'avais aussi trouver dans MyDac mais pas de doc à sujet dans la version que j'ai et je ne les retrouve pas !)

    J'aimerais bien savoir comment cela fonctionnait chez mon ancien employeur, ... faut dire que les requêtes ne récupérait jamais plus d'un milliers d'enreg ... et puis il y avait une archi 3-tiers complètes, et asynchrone au vu des mes tests ... (les objets query était en fait des descendants de TClientDataSet, et je pense que la requête était executé sur le serveur, et que la gestion de packet avait été refaite ...)
    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

  17. #17
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut, si tu utilises les composants MyDAC, demandes à CoreLab comment le gérer.
    Je sais par exemple que par défaut, la dll de Borland pour Interbase/Firebird ne remonte que les premiers enregistrements alors que la dll de CoreLab pour Interbase/Firebird ouvre et charge l'ensemble des enregistrements avant de rendre la main et qu'il est possible de paramétrer ce fonctionnement.
    Il se peut que ce soit la même chose avec les composants MyDAC de CoreLab.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [DBGRID] Comment coloriser 1 ligne sur 2 dans un DBGRID
    Par did85 dans le forum Bases de données
    Réponses: 28
    Dernier message: 26/10/2011, 15h22
  2. Réponses: 1
    Dernier message: 11/01/2007, 14h53
  3. [VBA]comptage de lignes en fonction du contenu des cellules
    Par calimero91 dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 22/12/2005, 11h38
  4. [vbexcel]Comptage de ligne
    Par Mugette dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 05/12/2005, 17h22
  5. [DBGRID][FAQ] Dessiner des lignes de couleur
    Par okparanoid dans le forum Bases de données
    Réponses: 5
    Dernier message: 11/10/2005, 17h10

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