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

VB.NET Discussion :

class perso pour une connexion à SQL server


Sujet :

VB.NET

  1. #1
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 52
    Par défaut class perso pour une connexion à SQL server
    Bonjour,

    J'ai en charge le développement d'une gestion commerciale (devis, facture, gestion du stock...). J'ai choisi de le développer en VB.net avec une base SQL server. Pour bien débuter le projet, je suis en train de faire des test de connection à la base de données. Dans un projet précédent je perdai beaucoup de temps à me connecter (très souvent) à ma base SQL et je souhaiterais avoir votre avis à ce sujet. Serait-il possible de se créer une class perso pour cela ?

    Ma problématique c'est que je vais devoir interroger une grosse base de données avec quelques fois des 2 ou 3 requêtes imbriquées et très souvent.

    J'utilise "System.Data.SqlClient" pour me connecter à la base SQL, et une fois le sqlcommand et le sqlconnection géré plus un try pour tester si tout se passe bien, ça fait vite une dizaine de lignes à copier/coller juste pour interroger la base et changer seulement la requête SQL et la réception des données. Je me demandais alors si il n'était pas possible de se créer une class. Par exemple comme ceci :

    Déclaration de la class mgcDB :

    ------------
    Code VB.Net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Imports System.Data.SqlClient
    Public Class mgcDB
    Public DBSource = "data source=SQLEXPRESS;initial catalog=BASE_TEST;Uid=test;Pwd=test;Connection Timeout=100000; Pooling=False"
     
     Public Function ConnectionExecuteReader(ByVal sql)
            Dim cnx_sql_base As New SqlConnection(DBSource)
            Dim cmd_sql_base As New SqlCommand()
            cmd_sql_base.Connection = cnx_sql_base
            cmd_sql_base.CommandText = sql
            cnx_sql_base.Open()
            Dim result = cmd_sql_base.ExecuteReader(CommandBehavior.CloseConnection)
            Return result
    End Function
    ------------

    Ca fonctionne si je crais par exemple une requette imbriquée dans mon form1 comme ceci :

    ----------
    ' J'importe ma class perso
    Code VB.net : 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
    Imports MGC.mgcDB
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
     
    Dim myconnection = New mgcDB
            Dim result = myconnection.ConnectionExecuteReader("select count(*) from Table")
           Do While result.Read
                Dim tmp = result.GetValue(0)
                Dim result2 = myconnection.ConnectionExecuteReader("select * from Table")
                Do While result2.Read
                    Dim tmp2 = result2.GetValue(0)
                    MsgBox(tmp & " => " & tmp2)
                Loop
            Loop
     
            myconnection.Close()
    End Sub
    ----------

    J'ai bien mes deux requêtes imbriqués qui se connectent à ma base SQl server avec un minimum de code (grâce à ma class perso). De plus je pourrait rajouter un "try" dans ma class pour gérer les erreurs de connection. Le problème c'est que je ne pense pas que "myconnection.Close()" ferme correctement la connection à ma base de données (je la ferme pas dans ma class), et dans ce cas je risque de vite avoir des problème de performence ou de mémoire. L'application devra être utilisé par une centaine d'utilisateurs en même temps.

    Qu'en pensez vous ? Et-il possible de créer une class perso pour se connecter à SQL server en un minimum de code ?

    Merci pour votre aide ;-)

    PS : ah oui au fait, j'ai longtemps hésité à utiliser PHP, cShapre ou VB.net pour ce projet. J'ai choisi VB.net car il est simple à utiliser et on peut rapidement créer des formulaires ou des exports word, excel, pdf... ce qui est parfait pour du développement "métier".

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    il est en effet recommandable de faire sa propre classe de connexion
    néanmoins elle devra faire quelques lignes de plus pour être plus efficace ^^

    si tu dois faire plusieurs install, le chemin d'accès aux données doit être paramétrable plutot qu'en dur dans le code (fichier ini ou autre)
    si un même programme doit pouvoir se connecter à plusieurs base, la connexion en dur ou en semi dur ne suffit pas, il faut alors une propriété modifiable par code

    la connexion doit être une variable de classe plutot que de membre pour pouvoir être fermée
    et pour la libération des ressources, il faut appeler .dispose dessus
    donc le mieux est de rendre ta classe disposable aussi (implement IDisposable)

    j'ajouterais aussi qu'il faut gérer les dbparameters

    il ne faut pas gérer que l'executereader, l'executenonquery est important aussi

    et il serait aussi possible d'exposer des tas de propriétés et méthodes si tu en as besoins (executetimeout, transactions etc...)

    NB : il est préférable de typer tes fonctions et d'activer explicit on et strict on (propriétés du projet et/ou propriétés de vb pour les futurs projets)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 52
    Par défaut
    Bonjour Pol63

    Merci de me donner un coup de main, tu as l'air de bien t'y connaitre et avoir de l'expérience en VB.net (j'ai beaucoup de travail dans ce domaine car mon projet n'est que le deuxième et je voudrai vraiment partir sur de bonnes bases ;-) )

    Suite à tes conseils j'ai modifié mon code et j'aurais souhaitez avoir ton avis (est-ce que je suis dans le vrai, et si oui est-ce que je peux encore l'obtimiser)

    Ma class ressemble à ça :
    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
     
    ' CLASS permettant de se connecter à une base de donnée SQLSERVER
    Imports System.Data.SqlClient
     
     
    Public Class mgcDB
        Implements IDisposable
        Public cnx_sql_base As New SqlConnection(My.Settings.DBsource)
        Public cmd_sql_base As New SqlCommand()
        Public result As String
        Public reader As SqlDataReader
        Public Requete As String
     
        Public Function ConnectionScalar() As String
            Me.cmd_sql_base.Connection = cnx_sql_base
            Me.cmd_sql_base.CommandText = Me.Requete
            Try
                Me.cnx_sql_base.Open()
                Me.result = cmd_sql_base.ExecuteScalar().ToString
            Catch ex As Exception
                MsgBox("Erreur : " & ex.Message)
            Finally
                Me.cmd_sql_base.Dispose()
                Me.cnx_sql_base.Close()
                Me.cnx_sql_base.Dispose()
            End Try
     
            Return result
        End Function
     
        Public Function ConnectionExecuteReader() As SqlDataReader
            Me.cmd_sql_base.Connection = cnx_sql_base
            Me.cmd_sql_base.CommandText = Me.Requete
            Try
                Me.cnx_sql_base.Open()
                Me.reader = cmd_sql_base.ExecuteReader(CommandBehavior.CloseConnection)
            Catch ex As Exception
            Finally
                ' JE NE PEUX PAS FERMER MA CONNECTION ICI ALORS ELLE SE FERA PAR LA FONCTION DISPOSE
                'cnx_sql_base.Close()
            End Try
     
            Return reader
        End Function
     
        Public Sub Dispose() Implements System.IDisposable.Dispose
            Try
                Me.Requete = Nothing
                Me.cnx_sql_base.Close()
                Me.cnx_sql_base.Dispose()
                Me.cmd_sql_base.Dispose()
                Me.reader.Close()
                Me.result = Nothing
            Catch ex As Exception
     
            End Try
     
        End Sub
     
    End Class
    Pour l'instant j'ai développé que deux fonctions pour interroger la base de données, mais ce sont les plus compliqués. Si je suis dans le vrai, le reste ira tout seul.
    Ensuite j'ai testé ma class comme ceci :

    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
     
    Imports MGC.mgcDB
     
    Public Class Form1
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            MsgBox("Début du programme")
     
            ' Test de la CLASS avec une connection Scalar (un seul résultat)
            Dim myconnection = New mgcDB
            myconnection.Requete = "select count(*) from Test"
            myconnection.result = myconnection.ConnectionScalar()
            MsgBox(myconnection.result)
            ' Fermeture de la connection pour libérer la mémoire
            myconnection.Dispose()
     
            ' Test de la CLASS avec deux connections ExecuteReader (plusieurs résultats) imbriquées
            Dim myconnection2 = New mgcDB
            myconnection2.Requete = "select * from Test"
            myconnection2.reader = myconnection2.ConnectionExecuteReader()
            Do While myconnection2.reader.Read
                Dim tmp2 As String = myconnection2.reader.GetValue(0).ToString
                MsgBox(tmp2)
                ' Test de la CLASS avec une deuxième connection SQLSERVER Imbriquée
                Dim myconnection3 = New mgcDB
                myconnection3.Requete = "select * from Test"
                myconnection3.reader = myconnection3.ConnectionExecuteReader()
                Do While myconnection3.reader.Read
                    Dim tmp3 As String = myconnection3.reader.GetValue(1).ToString
                    MsgBox(tmp2 & " => " & tmp3)
                Loop
                ' Fermeture de la connection pour libérer la mémoire
                myconnection3.Dispose()
            Loop
     
            ' Fermeture de la connection pour libérer la mémoire
            myconnection2.Dispose()
     
            MsgBox("fin du programme")
        End Sub
    End Class
    Quand je test, ça fonctionne (c'est déjà pas mal) ;-)

    Quand tu parle de typer les fonctions, ca veux dire quoi ?

    Merci pour ton aide.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public result As String
    + la fonction qui retourne le string, il faut choisir l'un ou l'autre
    tant qu'à faire autant garder le retour
    par contre as string, c'est une mauvaise idée, quand on veut que tout soit possible et ne change pas de type on met as object, tout hérite de objet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Requete As String
    en théorie il faut une property plutot ca fait plus propre et c'est plus évolutif
    pour le reader il faut un readonly property, par défaut il faut interdire tout ce qui est illogique ou dangereux, que quelqu'un d'extérieur à la classe puisse modifier le reader stocké ici en fait partie
    (...)
    là aussi le reader soit tu le retournes, soit tu l'exposes
    tant qu'à faire choisit le même comportement dans les 2 cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Function ConnectionScalar() As String
    comme dit précédemment un decimal, une date ou encore un tableau d'octet dans un string, c'est loin d'être une bonne idée => As Object


    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
     Public Function ConnectionScalar() As String
            Me.cmd_sql_base.Connection = cnx_sql_base
            Me.cmd_sql_base.CommandText = Me.Requete
            Try
                Me.cnx_sql_base.Open()
                Me.result = cmd_sql_base.ExecuteScalar().ToString
            Catch ex As Exception
                MsgBox("Erreur : " & ex.Message)
            Finally
                Me.cmd_sql_base.Dispose()
                Me.cnx_sql_base.Close()
                Me.cnx_sql_base.Dispose()
            End Try
            Return result
        End Function
    le try catch c'est bien
    msgbox c'est très moyen, le mieux reste de laisser passer l'erreur, car l'appelant doit savoir s'il y a eut une erreur, genre pour arreter ce qu'il est en train de faire

    cnx.dispose fait le .close
    disposer la connexion la rend inutilisable par la suite, ce qui oblige si l'appelant à 2 requete à faire à instancier 2 connexions


    mettre quelque chose à nothing est rarement utile, c'est automatique en sortie de portée


    Citation Envoyé par le_binr Voir le message
    Quand tu parle de typer les fonctions, ca veux dire quoi ?
    le as derrière
    dans ton premier code tu avais une fonction non typée (donc as object)
    et tu n'as pas les bons paramètres dans vb (option explicit et strict on)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 52
    Par défaut
    Merci Pol63 pour tes précieux conseils ;-)

    Je ne connaissais pas du tout les "Property",ça à l'air très pratique. Je vais me renseigner plus à ce sujet. Je l'ai intégré dans la class comme ceci :

    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    ' CLASS permettant de se connecter à une base de donnée SQLSERVER
    Imports System.Data.SqlClient
     
     
    Public Class mgcDB
        Implements IDisposable
        Public cnx_sql_base As New SqlConnection(My.Settings.DBsource)
        Public cmd_sql_base As New SqlCommand()
     
        Private _mRequete As String
        Public Property Requete() As String
            Get
                Return _mRequete
            End Get
            Set(ByVal value As String)
                _mRequete = value
            End Set
        End Property
     
        Private _mReader As SqlDataReader
        Public Property Reader() As SqlDataReader
            Get
                Return _mReader
            End Get
            Set(ByVal value As SqlDataReader)
                _mReader = value
            End Set
        End Property
     
        Public Function ConnectionScalar() As String
            Me.cmd_sql_base.Connection = cnx_sql_base
            Me.cmd_sql_base.CommandText = Me.Requete
            Dim result As New Object
            Try
                Me.cnx_sql_base.Open()
                result = cmd_sql_base.ExecuteScalar()
            Catch ex As Exception
                MsgBox("Erreur : " & ex.Message)
            Finally
                Me.cmd_sql_base.Dispose()
                Me.cnx_sql_base.Close()
                Me.cnx_sql_base.Dispose()
            End Try
     
            Return CStr(result)
        End Function
     
        Public Function ConnectionExecuteReader() As SqlDataReader
            Me.cmd_sql_base.Connection = cnx_sql_base
            Me.cmd_sql_base.CommandText = Me.Requete
            Try
                Me.cnx_sql_base.Open()
                Me.Reader = cmd_sql_base.ExecuteReader(CommandBehavior.CloseConnection)
            Catch ex As Exception
            Finally
            End Try
     
            Return reader
        End Function
     
        Public Sub Dispose() Implements System.IDisposable.Dispose
            Try
                Me.Requete = Nothing
                Me.cnx_sql_base.Close()
                Me.cnx_sql_base.Dispose()
                Me.cmd_sql_base.Dispose()
                Me.reader.Close()
            Catch ex As Exception
     
            End Try
     
        End Sub
     
    End Class
    et l'utilisation de la class comme ceci :

    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
     
    Imports MGC.mgcDB
     
    Public Class Form1
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            MsgBox("Début du programme")
     
            ' Test de la CLASS avec une connection Scalar (un seul résultat)
            Dim myconnection = New mgcDB
            myconnection.Requete = "select count(*) from Test"
            Dim result As Object = myconnection.ConnectionScalar()
            MsgBox(result)
            ' Fermeture de la connection pour libérer la mémoire
            myconnection.Dispose()
     
            ' Test de la CLASS avec deux connections ExecuteReader (plusieurs résultats) imbriquées
            Dim myconnection2 = New mgcDB
            myconnection2.Requete = "select * from Test"
            myconnection2.ConnectionExecuteReader()
            Do While myconnection2.reader.Read
                Dim tmp2 As String = myconnection2.reader.GetValue(0).ToString
                MsgBox(tmp2)
                ' Test de la CLASS avec une deuxième connection SQLSERVER Imbriquée
                Dim myconnection3 = New mgcDB
                myconnection3.Requete = "select * from Test"
                myconnection3.ConnectionExecuteReader()
                Do While myconnection3.reader.Read
                    Dim tmp3 As String = myconnection3.reader.GetValue(1).ToString
                    MsgBox(tmp2 & " => " & tmp3)
                Loop
                ' Fermeture de la connection pour libérer la mémoire
                myconnection3.Dispose()
            Loop
     
            ' Fermeture de la connection pour libérer la mémoire
            myconnection2.Dispose()
     
            MsgBox("fin du programme")
        End Sub
    End Class
    Je pense que je vais partir sur cette base comme class de connection. ET l'a faire évoluer au fur et à mesure (surtout au niveau des fonctions manquantes). Qu'en penses-tu ?

    Pour les erreurs signalés par msgbox tu me conseillerai plutôt de les utiliser comment ?

    Encore merci pour ton aide et pour ce forum. J'ai encore pleins d'idées et de questionnements sur l'évolution du projet qui feront l'objet d'autres posts si je ne trouve pas mon bonheur dans ceux déjà existants ;-)

    Merci pour votre aide.

  6. #6
    Rédacteur
    Avatar de WOLO Laurent
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Mars 2003
    Messages
    2 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 741
    Par défaut
    Code VB.Net : Sélectionner tout - Visualiser dans une fenêtre à part
    Public DBSource = "data source=SQLEXPRESS;initial catalog=BASE_TEST;Uid=test;Pwd=test;Connection Timeout=100000; Pooling=False"

    Active le pool de connexion aussi pour accelerer.

    Code VB.Net : Sélectionner tout - Visualiser dans une fenêtre à part
    Public DBSource = "data source=SQLEXPRESS;initial catalog=BASE_TEST;Uid=test;Pwd=test;Connection Timeout=100000; Pooling=True"

    Découvrez la FAQ de MS SQL Server.
    La chance accorde ses faveurs aux esprits avertis !

  7. #7
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 52
    Par défaut
    ok, merci pour le conseil WOLO ;-)

    Ça va bien m'aider car je vais traiter 30 000 articles et une centaine de ventes clients et d'achats fournisseurs par jour (il faudra que je me penche sur l'historisation de tous les mouvement pour ne pas alourdir la base au bout de quelques mois d'utilisation). Il faudra bien que je paramètre mes liaisons. Mais avant de créer ma base de données je crais mes formulaires de saisie afin de mieux visualiser l'application dans sa globalités, et ensuite définir au mieux la base de données. Ma table articles sera assez lourde (30 000 produits) et aura de nombreux champs que je suis en train d'identifier (libellé, code interne, code fournisseur, prix d'achat, prix de vente, conditionnement, délais de livraison, unité de facturation...) avec des tables jointes (rangement dans plusieurs entrepôts , plusieurs tarifs en fonction des clients...)... c'est là qu'il ne faut pas que je me plante.

    Merci pour votre aide ;-)

  8. #8
    Membre éclairé
    Inscrit en
    Novembre 2006
    Messages
    262
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 262
    Par défaut
    bonjour,

    déja merci pour cette classe, ça m'a énormément aidé;
    permettez moi de remettre le sujet sur le tapis, mais je voudrais savoir dans la cas ou on utilise des requêtes paramétré, comment peut on utiliser cette classe dans ce cas, surtout si le nombre de paramètre est variable d'une requête a une autre.

    Merci.

Discussions similaires

  1. [2012] Appli basique pour tester une connexion SQL Server
    Par annedeblois dans le forum Outils
    Réponses: 11
    Dernier message: 06/08/2013, 18h55
  2. Spécifier "program_name" pour une connexion SQL Server
    Par Nono23 dans le forum Bases de données
    Réponses: 4
    Dernier message: 10/03/2010, 16h11
  3. Probleme de droit avec une connexion sql server 2005
    Par mduarte dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 27/08/2007, 10h12
  4. Aidez moi pour une requête SQL server
    Par pop10 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 19/06/2007, 22h15
  5. Impossible d'ouvrir une connexion à SQL Server
    Par lamiruth dans le forum Accès aux données
    Réponses: 1
    Dernier message: 18/02/2007, 15h40

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