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

ASP Discussion :

Utilisation d'un dictionnaire pour copier un recordset


Sujet :

ASP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut Utilisation d'un dictionnaire pour copier un recordset
    Ce message vient de reponses postées dans la discussion : http://www.developpez.net/forums/d50...ommentaires-o/


    Salut,

    Merci pour ces codes.
    Est-ce que tu peux mettre le code de la classe cDB?

    Par contre, en ASP3, par experience, ce n'est pas forcement très performant de créer une connexion pour chaque requete. Il vaut mieux en créer une par page asp et utiliser uniquemment celle là en la transmettant aux classes, fonctions et procédures par l'intermédiaire d'une propriété ou un paramètre.

    Pour ce qui est des de libérer la connexion et utiliser le recordset obtenu, c'est tout à fait possible en utlisant un curseur client (tout ceux qui renvoi un recordcount différent de -1). Ce recordeset est "détaché" et lisible plusieurs fois (on peut revenir au début).

    A+
    "Winter is coming" (ma nouvelle page d'accueil)

  2. #2
    Modérateur
    Avatar de roro06
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    1 480
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 480
    Par défaut
    Bonjour

    Je suis avec intérêt cette rubrique depuis le début, même si je n'y contribue pas (pas encore).

    ce n'est pas forcement très performant de créer une connexion pour chaque requete
    Absolument, je dirai même que c'est à proscrire.

    quelques remarques :

    Dans le cas de la fonction a_data, tu boucles 2 fois sur le recordset, la première fois pour compter le nombre d'enregistrements, la deuxième fois pour créer autant d'objets dictionnary que d'enregistrements.

    Je pense que cette méthode risque d'aller à contre-sens de l'objectif initial, à savoir de "fermer la connexion dés que possible", particulièrement sur des jeux d'enregistrements un peu "gros" (je rappelle : 1 dictionnary par enregistrement ! imagine si tu as 50 000 enregistrements, et trente clients en même temps).
    Je pense qu'une simple boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while not rs.eof
    response.write elt("Nom") & "<br>"
    response.write elt("Prenom") & "<br>"
    response.write elt("Adresse") & "<br>"
    rs.movenext
    wend
    A plus de chances d'être plus performante en terme de rapidité et de ressources machine.

    Attention également :
    set dico = createObject("Scripting.Dictionary")
    Utilise plutôt, en ASP3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set dico = server.createObject("Scripting.Dictionary")


    N'oubliez pas de consulter les FAQ ASP et les cours et tutoriels ASP

    " La vie c'est quelque chose de très fort et de très beau.... La vie appartient a tous les vivants. It's both a dream and a feeling. C'est être ce que nous ne sommes pas sans le rester. La vie c'est mourir aussi....Et mourir c'est vraiment strong...c'est rester en vie au delà de la mort...Tous ceux qui sont morts n'ignorent pas de le savoir."
    (J.C. VanDamme, humoriste et philosophe belge . A moins que ce ne soit l'inverse ...)

    Chuck Norris comprend JC Van Damme.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 112
    Par défaut
    Salut tous les deux et merci de vos interventions.

    Je répond par étape et vais essayer de ne rien oublier.

    Alors le code de la classe c'est le tiens en fait, je ne fais qu'y passer la chaine de connexion que j'ai au préalable placé dans un fichier ini.asp, en constante :
    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
     
    Class cDB
     
            ' Les variable privées sont inaccessibles depuis l'exterieur
            ' nous les consulterons par l'intermediaire de leurs propriétés nommées "accessers".
            ' Les accessers sont comme des fonctions.
            Private m_Provider ' variable privée de la chaine de connection
            Private oConn ' objet privée de connection
            Private oCmd ' objet privé de command
     
            ' Ce que va faire la classe au moment de son instanciation
            ' 1 - Créer une connection ADO
            ' 2 - Créer une command ADO
            Private Sub Class_Initialize
                    Set oConn = Server.CreateObject("ADODB.Connection")
                    Set oCmd = Server.CreateObject("ADODB.Command")
                    m_Provider = CONN_STRING
    				' Au moment où nous allons assigner une valeur à la chaine de connection, nous allons l'ouvrir.
                    oConn.ConnectionString = m_Provider
                    oConn.Open()
                    ' Nous lions la command à l'objet connection
                    oCmd.ActiveConnection = oConn
            End Sub
     
            ' Ce que va faire la classe au moment de sa destruction
            ' 1 - detruire l'objet command
            ' 2 - fermer la connection si elle est encore ouverte
            ' 3 - détruire l'objet connection
            Private Sub Class_Terminate
    				Set oCmd = Nothing
                    If oConn.State = 1 then oConn.Close()
    				Set oConn = Nothing
            End Sub
     
            ' Cette propriété execute la requete SQL et renvoi le recordset correspondant
            Public Function SQL(sSQL)
                oCmd.CommandText = sSQL
                    Set SQL = oCmd.Execute()
            End Function
    End Class
    En suite, tu préfères créer une connexion au début de la page et la fermer... Je n'ai pas bien compris quand d'ailleurs, je suppose en fin de page ?

    Si j'ai bien compris ton point de vue, je ne suis pas d'accord pour des questions de surcharge sur la base justement.
    C'est à dire que si tu as trop de personnes connectées en même temps sur ton site, tu as de fortes chances d'obtenir ce maudit message : "trop de connexions ouvertes en même temps".

    Je suis cependant d'accord avec le fait qu'ouvrir et fermer les connexions à chaque fonction alourdi le traitement. Mais, de ce que j'ai pu en constater de visu, il doit s'agir de quelques millisecondes puisque je ne l'ai pas "ressenti".

    Enfin, si j'ai bien compris ce que tu me dit, on peut libérer la mémoire d'un RS et par la suite le travailler ? o_O
    Si c'est bien ça alors je prendrais le temps de "comprendre" cette histoire de curseur à laquelle tu fais référence...
    J'ai regardé rapidement la page que tu donnes en lien et elle mérite plus ample attention Mais ça m'intéressera alors beaucoup.

    En suite Roro, hum... Je ne comprends pas vraiment en fait.
    J'utilise le bon vieux i++ pour ne pas utiliser le .count qui non seulement est dévoreur de temps (constaté de visu) mais en plus n'est pas compatible avec toutes les versions d'Access.
    Ce i++ n'est fait qu'une seule fois par fonction, pas à chaque boucle hein...
    Certes ça alourdi un peu le code et ce n'est pas très... propre mais ça reste très efficace, ce que je recherche.
    En soit, ça n'a aucun impacte sur le fait de fermer ou non ma connexion.

    En suite tu dis :
    (je rappelle : 1 dictionnary par enregistrement ! imagine si tu as 50 000 enregistrements, et trente clients en même temps)

    Oui, ce que tu dis sous entend que le fait de créer puis de fermer un dico prend beaucoup de temps ?
    Franchement j'ai un sérieux doute, je sais pas...
    Bon, je vais regarder ça aujourd'hui, je vais créer une table avec 400.000 enregistrements et tester les deux solutions, j'en aurais le coeur net.

    Enfin, je ne souhaite pas utiliser directement les RS dans les pages principales comme tu le suggères pour cette fameuse raison de trop plein de connexion simultanées sur le serveur, erreur bloquante !
    Donc c'est mon objectif n°1, il est inadmissible pour mes clients de supporter ce genre de chose, je les comprends tout a fait
    A moi de ménager la chèvre et le choux et de trouver une solution même si elle ralentie un peu l'usager, je préfères, tu le comprendras, une appli un peu plus lente qu'une appli qui ne marche pas du tout...

    Encore merci pour vos deux interventions, j'apprécie grandement d'échanger avec vous.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 112
    Par défaut
    Ah, j'oubliais, remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    set dico = createObject("Scripting.Dictionary")
    par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    set dico = server.createObject("Scripting.Dictionary")
    Merci, c'est noté, j'ai fait les modifs nécessaires.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 112
    Par défaut
    Bien !

    Donc, j'ai fait une table "Temp" dans laquelle j'ai placé 400.000 enregistrements.
    Puis, j'ai retourné le résultat d'un SELECT * avec les deux méthodes.

    Méthode 1 => création et destruction d'un dico pour chaque enreg, bilan après deux minutes environ, le script plante :

    Erreur de compilation Microsoft VBScript error '800a03e9'
    Mémoire insuffisante
    /iisHelp/common/500-100.asp, line 0
    Objet Server error 'ASP 0177 : 80004002'
    Échec de Server.CreateObject
    /projet/lib/fct_array.asp, line 25
    Cette interface n'est pas prise en charge
    La ligne 25 correspond à la création du dico.
    Peut-être serait-il bon de placer un petit response.flush ? Je vais tester.

    Donc, hors mis le plantage que je peux peut-être corriger, je ne connais pas encore le temps d'exécution de la requête.

    Méthode 2 => création d'un RS, je boucle directement dessus et je response.write de la page mère.

    Le script ne plante pas, durée de l'opération : un peu plus de 6 minutes...
    conclusion : 6 minutes durant lesquelles la connexion reste ouverte.

    Je vais essayer de libérer le buffer plus souvent pour la 1ère méthode.
    D'autre part je vais regarder de plus près cette histoire de "curseur client" dont tu m'as parlé.

    Quoi qu'il en soit, je suis en train de mélanger deux problèmes et je ne devrais dans un 1er temps.
    1 - beaucoup de personnes qui ouvrent et ferment des connexions = "Trop de conn ouvertes en même temps". Pour ça ma solution semble correcte (si pas trop d'enregistrements travaillés à la fois par un même script (mais j'aime pas du tout ce plantage, quoi qu'il en soit, je dois le régler).
    2 - un grand nombre d'enregistrements à traiter au plus vite.

    Évidemment si au final je peux n'avoir qu'une seule et même solution, ce sera idéal et c'est dans cette direction que je souhaite aller in fine.

    ++

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 112
    Par défaut
    Bon, je viens de faire un nouveau test vraiment intéressant.
    Au lieu d'afficher l'ensemble des résultats, je les affiche par tranche de 10K, bilan des courses l'exécution prend environ 1 seconde avec le RS et encore plus de 20 secondes avec ma fonction a_data.
    Étonnant comme "response.write" rallonge les traitements. Remarquez je me souviens qu'en "C" la fonction "print" était énorme !!

    Roro tu avais raison, cette méthode n'est vraiment pas recommandée (création puis destruction du dico pour chaque enreg) lorsqu'on a de nombreux enreg à traiter.
    En revanche elle permet toujours de fermer la connexion tout en continuant à traiter les infos trouvées (puisque stokées dans un array, donc indépendant du RS initial).

    Je viens de regarder d'un peu plus près la configuration de la connexion : type de curseurs et de verrous.
    Alors je ne pense pas que ça puisse m'aider à fermer la connexion tout en continuant à travailler sur mon RS (ou alors j'ai loupé quelque chose).
    A moins que le verrou "adLockReadOnly" et un curseur "Static" permettent justement ça ?

    ++

  7. #7
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    ce n'est pas forcement très performant de créer une connexion pour chaque requete
    Absolument, je dirai même que c'est à proscrire.
    Pourquoi?
    Oui et non, en cas de doute la bonne pratique reste "créer tard, detruire tôt". En ASP3, les connections sont très mal gérées. Dans le cas d'un site à fort trafic, on peut rapidement les faire grimper saturer le serveur de données. Il vaut donc mieux en créer une au début du script la transmettre et la fermer en fin de script.

    A+
    "Winter is coming" (ma nouvelle page d'accueil)

Discussions similaires

  1. utiliser uiputfile pour copier un fichier
    Par dzdesperado dans le forum Interfaces Graphiques
    Réponses: 3
    Dernier message: 13/05/2013, 21h32
  2. Réponses: 4
    Dernier message: 13/07/2011, 14h46
  3. utiliser lockbits pour copier une image
    Par Pol63 dans le forum VB.NET
    Réponses: 2
    Dernier message: 05/11/2008, 15h40
  4. Réponses: 2
    Dernier message: 29/07/2008, 18h08
  5. Utiliser mon tableau pour copier des fichiers
    Par Paloma dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 31/10/2006, 18h38

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