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

Dotnet Discussion :

Procedure stockée dans une boucle.


Sujet :

Dotnet

  1. #21
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    ok je vais essayer je reviens vers vous.
    Et d'après vous cela expliquerait que le code marche à 99% sauf lors d'un trop grand nombre d'appel?

    Citation Envoyé par François DORIN Voir le message
    Effectivement, ce n'est pas suffisant. Il faut appeler la méthode Dipose dès lors que l'object n'est plus nécessaire. Il en manque donc un dans RecupererParametre, qui instancie un objet SqlCommand si le cache n'existe pas.
    C'est bizarre tout de même, a moins d'un problème de cache. La procedure appelé est utilisé au minimum 231 fois par fichier. Elle est forcément en cache.

    - Note: J'ai retiré hier soir le fichier avec 30000 valeurs. Le service a fonctionné toute la nuit sans problème (3600 fichier traités).

  2. #22
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Je ne garantie pas que le problème vienne de là, mais ça peut !

    Et comme l'exception fait référence à un DataReader, et que le seul endroit où il puisse y en avoir un a priori est dans la méthode qui récupère la liste des paramètres d'une procédure stockée, je trouve intéressant d'aller jeter un oeil dans cette direction, et éliminer des sources potentielles d'erreur...
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  3. #23
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    pas de problème, j'essai de suivre votre résonnement.

    J'ai mis en place. Je vous tiens au courant. Dans la nuit, un fichier contenant 34867 valeurs est passé avec succès.

  4. #24
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Si tu ne fais pas d'executereader le dataadapter doit en faire un, verifie si tu ne peux pas le disposer

    Sinon indirectement si tu ouvres et fermes la connexion sql à chaque exécution (ou bloc de requêtes) comme c'est recommandé tu n'auras plus de problème
    Par ce que si ta connexion plante (car ca peut arriver qu'elle se ferme) ton programme continue t il de fonctionner ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #25
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    La connexion s'ouvre si elle n'est pas existante ou ouverte.

    Après la mise en place, j'ai remis en ligne le fichier de 30000 ligne. Plantage immédiat du service. J'ai comparé les donnés avec celui de 34000 lignes. Pas de soucis de ce coté. Par contre 2 différence me sont apparu:
    - l'heure de traitement , celui de jour qui ne passe pas, celui de nuit passe.
    -> le serveur est moins sollicité la nuit. Je ne peux rien y faire.

    - le temps de traitement (que je trace).
    -> pour 30000 lignes, il faut 32 à 39 secondes pour insérer chaque ligne. Du coup on passe largement au dessus de mon timer de 6 secondes. Peut être que cela à une incidence.
    J'ai donc arrêter le timer avant le traitement des lignes, puis remis en route à la fin du traitement. Miracle le fichier de 30000 est passé.

    Si vous avez une explication sur ce phénomène...

  6. #26
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par KyoshiroKensei Voir le message
    -> pour 30000 lignes, il faut 32 à 39 secondes pour insérer chaque ligne. Du coup on passe largement au dessus de mon timer de 6 secondes. Peut être que cela à une incidence.
    J'ai donc arrêter le timer avant le traitement des lignes, puis remis en route à la fin du traitement. Miracle le fichier de 30000 est passé.
    Par timer, tu veux dire timeout ? Si oui, je pense avoir l'explication. Si non, il faut que tu nous dises ce que fait ton timer !

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
         Dim mCommande As SqlCommand = Nothing
                Dim mAdapter As SqlDataAdapter = Nothing
     
                Try
                    Select Case type
                        Case CommandType.Text
                            'Création d'une nouvelle commande
                            mCommande = CreerRequete(texteSql, tracerLog)
     
                        Case CommandType.StoredProcedure
                            'Création d'une nouvelle commande
                            mCommande = CreerCommande(texteSql, tracerLog, valeurs)
     
                    End Select
     
                    'Création de l'adaptateur de données
                    mAdapter = New SqlDataAdapter(mCommande)
     
                    'Recuperation des donnees
                    RecupererDonnees = New DataSet
     
                    mAdapter.Fill(RecupererDonnees, nomTable)
     
                    If RecupererParametre Then
                        'Recuperation des parametres
                        mParametres = mCommande.Parameters
                    End If
     
     
     
                    'Indique la fin de l'execution de la requete
                    'GestionErreur.EnvoyerMessage(Me, MethodBase.GetCurrentMethod, "Execution de la requête terminée. (" & texteSql & ")")
                    If tracerLog Then
                        RaiseEvent TraceChange(Me, _
                                                 New ApplicationEventArgs(MethodBase.GetCurrentMethod, _
                                                                          Nothing, _
                                                                          "Execution de la requête terminée. (" & texteSql & ").", _
                                                                          TypeTrace.Debug, _
                                                                          TypeAffichage.Aucun))
                    End If
     
                Catch ex As Exception
     
                    'Leve une exception pour l'appelant
                    Throw New ApplicationErreur("L'execution de la requête a échouée. (" & texteSql & ")", _
                                                ex, _
                                                TypeTrace.Grave, _
                                                TypeAffichage.Bandeau, _
                                                "")
     
                Finally
     
                    If Not mAdapter Is Nothing Then
                        mAdapter.Dispose()
                    End If
                    mAdapter = Nothing
     
       'fermeture de la commande afin d'etre sur de le detruire rapidement.
                    If Not mCommande Is Nothing Then
                       mCommande.Dispose()
                       mCommande = Nothing
                    End If
                End Try
    Regarde bien le code, j'ai modifié l'endroit où est libérée mCommande. Au lieu de le faire dans le bloc Try, je le fais dans le bloc Finally.

    La différence entre les deux peux expliquer la différence de comportement que tu obtiens.

    Avec ton code, si tout se passe bien (pas de timeout), alors la mCommande est bien libérée. Pas de problème de ressource, et tout passe.
    Si par contre, survient une exception (et un timeout en génère une), alors tu passes dans le bloc Catch, et mCommande n'est pas libérée.

    Déplacer la libération dans la clause Finally assure que quelque soit l'issu (exception ou pas exception), la ressource est libérée si elle existe.

    Ce scénario peut tenir la route si l'exception que tu lèves par la suite (ApplicationErreur) est rattrapée par le code appelant...
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  7. #27
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    J'ai fais la même modif. Le dispose hors finally était juste pour le test.

    Le timer est un timer de System.Timers.timer. Il ne fait rien d'autre que de déclencher le traitement d'un fichier toutes les 6 secondes.

    Pour le timeout de ma connexion, il est fixé à 60 secondes.

  8. #28
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par KyoshiroKensei Voir le message
    Le timer est un timer de System.Timers.timer. Il ne fait rien d'autre que de déclencher le traitement d'un fichier toutes les 6 secondes.
    Ben ça, ça change tout ! Surtout si l'objet connexion est le même pour tous les traitements !

    Et la source de tes ennuis vient alors très certainement de là et des accès concurrentiels, car SqlConnection n'est pas thread safe. Inutile donc de chercher plus loin...
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  9. #29
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    Je ne comprends pas ta réponse.

    La connexion est créé (dll singleton) au démarrage du service. A chaque tick de mon timer tout les 6 secondes, le lance la requête qui traite les lignes du fichiers. Je ne fais rien d'autre dans ce processus.
    Donc même si je dépasse les 6 secondes de mon timer, pour moi, le service ne fait rien tant que le tick précédent n'est pas terminé.

    Peux tu développer ta réponse?

  10. #30
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Pour être sur de la réponse à donner, peux-tu me donner le code d'initialisation du timer ? Et le type de timer que tu utilises ? (System.Timers.Timer ? System.Threading.Timer ? System.Windows.Timer.Form ? Autre ?)
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  11. #31
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    Pour être sur de la réponse à donner, peux-tu me donner le code d'initialisation du timer ? Et le type de timer que tu utilises ? (System.Timers.Timer ? System.Threading.Timer ? System.Windows.Timer.Form ? Autre ?)
    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
     
    Private WithEvents mTimer As System.Timers.Timer
    
        Protected Overrides Sub OnStart(ByVal args() As String)
            ' Ajoutez ici le code pour démarrer votre service. Cette méthode doit
            ' démarrer votre service.
            Dim lMessage As String = ""
    
            Try
    
                If Not app.InitialiserClient(Environment.MachineName & "/" & Environment.UserName, _
                                             "TransfertFichier", _
                                             NomServeurBDD, _
                                             NomBDD", _
                                             Utl, _
                                             Mdp) Then
    
                End If
                app.AccesBase.ExecutionTimeOut = 60
    
                mTimer = New System.Timers.Timer
                mTimer.Interval = 6
             
                lMessage = "Demararge du service  - interval de " + mTimer.Interval.ToString + " - ActiverTransposition: " + mAvecTransposition.ToString + " - Seuil Erreur: " + mSeuilErreurUS.ToString + "."
                app.AccesBase.Executer(CommandType.StoredProcedure, "Tracer", MethodBase.GetCurrentMethod.Name, lMessage, 2)
    
                mTimer.Start()
    
            Catch ex As Exception
                Constantes.TraiterErreur(MethodBase.GetCurrentMethod, ex)
            End Try
        End Sub

  12. #32
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Tu initialises bien un timer, mais tu ne relie à rien l'événement Elapsed. Du coup, le timer ne fait... rien !

    Ensuite, juste pour info, l'intervalle du timer est en milliseconde, pas en seconde. Donc il est déclenché toutes les 6ms et non toutes les 6s comme tu le disais précédemment.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  13. #33
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    Pardon pour les imprécisions:

    La valeur d'interval viens de la BDD. J'ai tapé en dur pour plus de lisiblité. J'ai bien 6000 en base.

    Tu m'a demandé l'init du timer, j'avais pas compris que tu voulais l'elapse.
    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
     
     
     Private Sub mTimer_Elapsed(sender As Object, e As Timers.ElapsedEventArgs) Handles mTimer.Elapsed
            Dim lMessage As String = ""
     
            Try
                If Not mImportEnCours Then
     
                    mImportEnCours = True
     
     
     
                    If TransfererFichierUsEnBase() Then
     
                        mImportEnCours = False
     
                        If mAvecTransposition AndAlso Not mTranspositionEnCours Then
                            mTranspositionEnCours = True
     
                            TransposerFichierUs()
                            mTranspositionEnCours = False
     
                        End If
     
                    End If
                End If
            Catch ex As Exception
                Constantes.TraiterErreur(MethodBase.GetCurrentMethod, ex)
            Finally
                mImportEnCours = False
                mTranspositionEnCours = False
     
                If CompteurErreurImport >= mSeuilErreurUS Then
                    lMessage = mSeuilErreurUS.ToString + " erreurs consécutives. Arret du timer."
                    app.AccesBase.Executer(CommandType.StoredProcedure, "Tracer", MethodBase.GetCurrentMethod.Name, lMessage, 3)
                    mTimer.Stop()
                     End If
            End Try
        End Sub

  14. #34
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 760
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Je pense avoir trouvé.

    Tu protèges ton callback via le booléen mImportEnCours. Mais regarde bien le bloc Finally : tu le réinitialise à false !

    Du coup, lors d'un import qui prend du temps, un tick du timer survient. Un thread du pool de thread est utilisé pour exécuter le callback. La première conditionnel teste mImportEnCours et trouve qu'il y a un import en cours. Et ne fait donc rien. Mais il y a un appel au bloc Finally qui réinitialise le booléen à True.

    L'import dure vraiment longtemps, un deuxième tick arrive. Le callback est rééxécutée et trouve qu'il n'y a pas d'import en cours et en commence donc un nouveau. Résultat des courses : tu as deux import simultanément ==> comportement imprévisible.


    Quand tu désactives le timer, cela résout le problème car tu n'as plus ce problème de bloc Finally qui vient réinitialiser le booléen mImportEnCours.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  15. #35
    Membre régulier
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2011
    Messages : 109
    Points : 96
    Points
    96
    Par défaut
    bien vu. Merci pour ton aide.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Appels de procedures stockées dans une proc stockée ?
    Par Nadaa dans le forum MS SQL Server
    Réponses: 12
    Dernier message: 17/07/2008, 10h32
  2. executer une procedure stockées dans une requete SELECT
    Par bleuerouge dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 08/08/2006, 17h23
  3. Réponses: 2
    Dernier message: 22/06/2006, 11h26
  4. Réponses: 2
    Dernier message: 24/03/2006, 09h55
  5. Réponses: 3
    Dernier message: 21/09/2004, 07h35

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