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 :

Lire et écrire en "même" temps dans une table access [Débutant]


Sujet :

VB.NET

  1. #1
    Membre à l'essai
    Homme Profil pro
    Chef d'entreprise
    Inscrit en
    Avril 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef d'entreprise
    Secteur : Services à domicile

    Informations forums :
    Inscription : Avril 2014
    Messages : 20
    Points : 13
    Points
    13
    Par défaut Lire et écrire en "même" temps dans une table access
    Bonjour à tous, et désolé si le sujet à déjà été traité mais je ne l'ai pas trouvé.
    En toute honnêteté je n'ai pas dépassé la cinquième page.

    J'utilise : Windows 8, Microsoft Visual Studio Express 2013 pour Windows desktop

    Mon problème: Je récupère des éléments de type String dans un fichier et je voudrais les stocker dans une base MAIS uniquement s'ils n'existent pas; j'ai plusieurs fichiers (9) et plusieurs types d'éléments différents (3) et plusieurs bases de données (2).
    Comme les opérations sont toujours les mêmes, mais pas dans les mêmes tables, j'essaye de développer des procédures communes.

    La Table Base a la structure suivante:
    Table Base
    IndexBase numérique entier long
    base texte court

    J'ai fait le code suivant:
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    Public Class DataTable
        ' Table Data
        '   IndexData as long
        '   Data as string
        '   IndexBase as long
     
        Private MonIndex As Long
     
        Private NomTable As String
        Private NomIndexData As String
        Private NomData As String
        Private NomIndexBase As String
        Dim MesEnreg As System.Data.OleDb.OleDbDataReader
     
        Public Sub New(ByRef LeNomTable As String, _
                       ByRef LeNomIndexData As String, _
                       ByRef LeNomData As String, _
                       ByRef LeNomIndexBase As String)
            MonIndex = 0
            NomTable = LeNomTable
            NomIndexData = LeNomIndexData
            NomData = LeNomData
            NomIndexBase = LeNomIndexBase
            BaseDétail.SQL_ViderLaTable(NomTable)
        End Sub
     
        Public Function ValeurIndex(ByRef Data As String, ByRef Base As String, ByRef Devanagari As String) As Long
            ' cette fonction vérifie si la clé Mot existe sinon la créée
            ' retourne l'index de la clé
            Dim IndexBase As Long
            Dim IndexMot As Long
            Dim Champs(2) As String
            Dim Valeurs(2) As String
            Dim Numérique(2) As Boolean
     
            ' on récupère l'index de la base; si elle n'existe pas, elle est créée au passage
            IndexBase = Table_Bases.ValeurIndex(Base, Devanagari)
            IndexMot = RetrouveIndex(Base)
            If IndexMot < 0 Then
                ' Ca n'existe pas, on le créé
                MonIndex = MonIndex + 1
     
                Champs(0) = NomIndexData
                Valeurs(0) = MonIndex
                Numérique(0) = True
                Champs(1) = NomData
                Valeurs(1) = Data
                Numérique(1) = False
                Champs(2) = NomIndexBase
                Valeurs(2) = IndexBase
                Numérique(2) = True
     
                BaseDétail.SQL_Add(NomTable, Champs, Valeurs, Numérique)
     
                IndexMot = MonIndex
            Else
                ' le mot existe déjà dans la base
                ' on ne fait rien
            End If
            ValeurIndex = IndexMot
        End Function
     
        Private Function RetrouveIndex(ByRef Data As String) As Long
            Dim SQL As String
            Dim Trouvé As Boolean
            Dim str As String
     
            SQL = "SELECT " & NomIndexData & "," & NomData & " FROM " & NomTable & " WHERE " & NomData & "=""" & Data & """;"
            BaseDétail.SQL_Select(SQL, MesEnreg)
            If MesEnreg.HasRows Then
                str = StrToHex(Data)
                Trouvé = (str = StrToHex(MesEnreg(NomData)))
                While Not Trouvé And MesEnreg.Read()
                    Trouvé = (str = StrToHex(MesEnreg(NomData)))
                End While
                If Trouvé Then
                    RetrouveIndex = MesEnreg(NomIndexData)
                Else
                    RetrouveIndex = -1
                End If
                MesEnreg.Close()
            Else
                RetrouveIndex = -1
            End If
        End Function
     
    End Class
    Ben oui ce n'est pas du texte ASCII; c'est du Sanskrit et du dévanagari d'où la fonction StrToHex qui permet de différencier les lettres Majuscules et minuscules

    J'ai développé les deux procédures suivantes dans une autre classe dont BaseDétail est une implémentation; cmd est une variable globale
    J'utilise aussi plusieurs bases de données différentes, mais elles ont grosso-modo la même fonction; stocker des mots et des caractéristiques dans des tables liées entre elles
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Public Interface DataBase
        Sub SQL_Select(ByRef SQL As String, ByRef LesEnreg As System.Data.OleDb.OleDbDataReader)
        Sub SQL_Add(ByRef NomTable As String, ByRef Champ() As String, ByRef Donnée() As String, ByRef Numérique() As Boolean)
        Function SQL_NbEnreg(ByRef NomTable As String, ByRef NomChamp As String) As Long
        Sub SQL_ViderLaTable(ByRef Nomtable As String)
        Function SQL_ValeurIndex(ByRef LesEnreg As System.Data.OleDb.OleDbDataReader, ByRef nomChampIndex As String, ByRef nomChampClé As String, ByRef Clé As String) As Long
    End Interface
    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
     
    Public Class BaseDeDonnées : Implements DataBase
        ' on n'utilise pas de base intégrée
        Private Cn As New System.Data.OleDb.OleDbConnection
        Private Cmd As New System.Data.OleDb.OleDbCommand
        Private rd As System.Data.OleDb.OleDbDataReader
     
    '... pour éviter un texte trop long
     
        Public Sub SQL_Select(ByRef SQL As String, ByRef MesEnreg As System.Data.OleDb.OleDbDataReader) Implements DataBase.SQL_Select
            If Not IsNothing(MesEnreg) Then MesEnreg.Close() ' au cas où
            Cmd.CommandText = SQL
            Try
                MesEnreg = Cmd.ExecuteReader()
            Catch ex As Exception
                Alerte("BasedeDonnées.SQL_Select", SQL, ex.ToString)
            End Try
        End Sub
     
        Public Sub SQL_Add(ByRef NomTable As String, ByRef Champ() As String, ByRef Donnée() As String, ByRef Numérique() As Boolean) Implements DataBase.SQL_Add
            Dim SQL As String
            Dim I As Integer
            Dim NbData As Integer
     
            NbData = Donnée.Length - 1
     
            For I = 0 To NbData
                Formate(Donnée(I))
                Formate(Champ(I))
            Next I
            SQL = "Insert InTo " & NomTable
            SQL = SQL & " (" & Champ(0)
            For I = 1 To NbData
                If Champ(I) <> "" Then SQL = SQL & ", " & Champ(I)
            Next I
            SQL = SQL + ") Values (" & Enrobe(Donnée(0), Numérique(0))
            For I = 1 To NbData
                If Champ(I) <> "" Then
                    SQL = SQL & ", " & Enrobe(Donnée(I), Numérique(I))
                End If
            Next I
            SQL = SQL & ")"
     
            Try
                Cmd.ExecuteNonQuery()
            Catch ex As Exception
                Alerte("BasedeDonnées.SQL_Add", SQL, ex.ToString)
            End Try
        End Sub
     
    '... pour éviter un texte trop long
     
     
        Public Sub New(ByRef NomBase As String)
            Dim Tmp As String
     
            Tmp = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source =" & NomBase
            Try
                Cn.ConnectionString = Tmp
                Cmd.Connection = Cn
                Cn.Open()
            Catch ex As Exception
                MessageBox.Show("BasedeDonnées.new" & vbCrLf & ex.ToString)
            End Try
        End Sub
    End Class
    Mon souci est que j'ai une exception me disant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    System.InvalidOperationException: Un DataReader associé à cette Command est déjà ouvert. Il doit d'abord être fermé.
       à System.Data.OleDb.OleDbCommand.ValidateConnection(String method)
       à System.Data.OleDb.OleDbCommand.ValidateConnectionAndTransaction(String method)
       à System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
       à System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
       à System.Data.OleDb.OleDbCommand.ExecuteReader()
       à WindowsApplication1.BaseDeDonnées.SQL_Select(String& SQL, OleDbDataReader& MesEnreg) dans C:\Users\Alain\Desktop\Maharabata\VB\DétailSanskrit\BaseDeDonnées.vb:ligne 40
    D'où ma question: auriez vous une (ou des) suggestions, voire un code plus correct ?

  2. #2
    Membre actif
    Homme Profil pro
    Developpeur
    Inscrit en
    Février 2013
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Février 2013
    Messages : 180
    Points : 271
    Points
    271
    Par défaut
    un programme est une suite d'instruction linéaire, si on veut faire plusieurs action en "même" temps, on va alors déclarer des nouveaux threads

    on va séparer 1 seconde en plusieurs fragment pour que chaque fragment puisse exécuter une partie de ton code, ce qui donnera un aspect de multi tache

    je te laisse te documenté dessus : http://drq.developpez.com/dotnet/articles/threads/

  3. #3
    Membre à l'essai
    Homme Profil pro
    Chef d'entreprise
    Inscrit en
    Avril 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef d'entreprise
    Secteur : Services à domicile

    Informations forums :
    Inscription : Avril 2014
    Messages : 20
    Points : 13
    Points
    13
    Par défaut Merci mais ce n'est pas ça
    Merci pour votre réponse, mais quand je dis "en même temps" ça veut dire vérifier d'abord que ça n'existe pas et enregistrer en suite dans la même table.
    Je ne peux même pas essayer avec un index unique car Access ne fait pas vraiment la différence entre majuscule et minuscule or ici c'est fondamental du fait d'une translitération.

    Je pense que mon souci est lié à ma méconnaissance de ce qui se passe vraiment.

    Ce n'est en aucun cas un problème de tâches en par à l'aile
    Je ne me lancerais jamais dans ce genre de choses d'autant que je ne traite que du texte.

    Mais merci quand même d'avoir répondu

  4. #4
    Membre actif
    Homme Profil pro
    Developpeur
    Inscrit en
    Février 2013
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Février 2013
    Messages : 180
    Points : 271
    Points
    271
    Par défaut
    Désoler pour le manque de compréhension

    alors si ce qu'il vous manque est un unique identifier pour pouvoir être sur que la chaine n'est pas déjà enregistré.
    il existe une solution assez simple :
    pour cela vous pouvez d'abord récupérer dans une liste vos enregistrement stocké en base (on est d'accord ce sont bien des chaine de caractère ?)
    pour dans un deuxième temps stocké dans une autre liste les chaine de vos fichier

    une fois vos deux liste créés vous pouvez exécuter un INSERT seulement si les chaines sont différentes
    et pour savoir si elles sont différentes vous pouvez transformer ces chaines en entier.

    je m'explique suivant la table ASCII (google) chaque caractère est identifié par un nombre a = 97 et A = 65
    il me semble qu'il existe des méthodes de conversion automatique
    pour le reste je vous laisse chercher

  5. #5
    Membre à l'essai
    Homme Profil pro
    Chef d'entreprise
    Inscrit en
    Avril 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef d'entreprise
    Secteur : Services à domicile

    Informations forums :
    Inscription : Avril 2014
    Messages : 20
    Points : 13
    Points
    13
    Par défaut Merci
    Bon ce n'est pas la solution, mais ça m'a permis de trouver l'erreur GROSSIERE

    Je ne fermais pas un des System.Data.OleDb.OleDbDataReader, en l'occurrence celui qui comptait les enregistrements.

    Le code a été corrigé comme suit
    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
     
        Public Function SQL_NbEnreg(ByRef NomTable As String, ByRef NomChamp As String) As Long Implements DataBase.SQL_NbEnreg
            Dim rd As System.Data.OleDb.OleDbDataReader
            Dim SQL As String
     
            SQL_NbEnreg = 0
            SQL = "SELECT Count(" & NomChamp & ") AS Nb FROM " & NomTable & ";"
            rd = SQL_Select(SQL)
            Try
                rd.Read()
                SQL_NbEnreg = rd.Item("Nb")
            Catch ex As Exception
                Alerte("BasedeDonnées.NbEnreg", SQL, ex.ToString)
                ' NbEnreg = 0; c'est déjà le cas on ne fait rien
            End Try
            rd.Close()
        End Function
    Et le problème est réglé

    Encore merci car même si ce n'était pas la solution, ça m'a grandement aidé dans la recherche du problème. (si je peux me permettre)

  6. #6
    Membre actif
    Homme Profil pro
    Developpeur
    Inscrit en
    Février 2013
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Février 2013
    Messages : 180
    Points : 271
    Points
    271
    Par défaut
    du coup pour l'avenir pour éviter ce genre d'erreur vous pouvez utiliser le mot clé using
    on créé un objet dans le using et au moment ou l'on sort du using l'objet est automatiquement détruit (même en cas de plantage)

    exemple d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Using cnx As IDbConnection = SQLAccess.seConnecter()
        Dim cmd As IDbCommand = SQLAccess.creerCommand(cnx, SELECT_ALLLIGNEPARDATE, CommandType.Text)
        SQLAccess.creerParametre(cmd, "@Date", dateSelectionner.Date, DbType.Date)
        retour = ListeLignesProductionPSB(cmd.ExecuteReader())
    End Using

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

Discussions similaires

  1. Débutant - lire un liens htm dans une table access..
    Par jaromyr dans le forum Modélisation
    Réponses: 8
    Dernier message: 21/12/2007, 21h26
  2. Réponses: 6
    Dernier message: 27/08/2007, 23h29
  3. lire champs dans une table access
    Par bouanane20 dans le forum VB.NET
    Réponses: 1
    Dernier message: 22/08/2007, 08h06

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