Perdita della connesione in navigazione pagine

di il
7 risposte

Perdita della connesione in navigazione pagine

MI scuso con gli amici del forum e con gli amministratori, ma per errore avevo postato questo nuovo problema in un post aperto precedentemente.
Lo ripropongo come nuovo post .

---------------------------------------------------------------- Problema caduta connessione con accdb

ho un problema di probabile caduta connessioneverso Access.
Sto creando una piccola applicazione utilizzando excel e access.
Nel Modulo Ho creato una sub in cui Effettuo la connessione.

' definizioni delle variabili utilizzabili in tutta l'applicazione
Public oConn As ADODB.Connection
Public rs1 As ADODB.Recordset
Public strConn As String
Public FieldKeyRic As Variant
Public FieldoutRicerca As String
Public Strsql_Ric As String
Public NSel As Integer
Public Ncampi As Integer
Public SelezionatoCampodaElenco As Boolean
Public NameClienteNew As String
Public TipoSearch As String ' S=Selettiva G=Generica
Public ArkSearch  As String  ' Archivio di ricerca  L=Località C=Clienti
Public TipoArk  As String    ' D = Da Ritirare   R = Rilasciato
Public DateKeyRic As Date
Public txtChiamante As Integer  ' numero della txtbox chiamante per frmzoom
Public UserLogged As Long    ' utente che si è loggato
Public Commarea As String   ' salvo il txt chiamante tra frmritiro e frmCliente
Public PathUser As String
-------------------------------------------- metodo per la connessiione a access
Public Function GM_ConnMDB()

    Dim oConn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim strSQL As String
    Dim PathUser As String

   PathUser = ActiveWorkbook.Path & "\Covesap.accdb;"
      
    strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & PathUser & "Persist Security Info=False;"
    
    ' Crea e apri la connessione
    Set oConn = New ADODB.Connection
    oConn.Open strConn

End Function

la prima form che utilizzo è la frmLogin in cui immetto le credenziali d'accesso.  <--------------- funziona e riesco ad accedere al db controllando i dati d'accesso.

effettuato il login apro la formGestione in cui devo inserire i dati specifici dell'applicazione.
la logica applicativa prevede di effettuare una ricerca per vissualizzare un elenco con i record inseriti in tabella.

Private Sub btnElenco_Click()

' ricerca operazioni inserite

    Dim rs3 As ADODB.Recordset
    Dim strSQL As String
    Dim Parametro As String
    
' imposto i campi per la gestione delle ricerche per generare elenchi

SelezionatoCampodaElenco = False
NSel = 1
Ncampi = 4
Strsql_Ric = " SELECT Pratica.ID, Pratica.Utente, Pratica.Intervento, T_Stato_Pratica.D_Stato_Pratica " & _
             " FROM T_Stato_Pratica INNER JOIN Pratica ON T_Stato_Pratica.ID_Stato_Pratica = Pratica.Stato " & _
             " ORDER BY Pratica.Utente"
 

frmRicerca.InitializeStrsql Strsql_Ric  ' passo la stringa da eseguire sulla form geenerica di elenco

frmRicerca.Show vbModal
txtUtente = ""
If SelezionatoCampodaElenco Then
    txtPratica = FieldKeyRic
Else
    Inizializza
    MsgBox "Nessuna selezione operata dall'utente", vbExclamation
End If

End Sub

nella pagina "frmRicerca" in cui effettuo la lettura dei dati contenuti nella Strsql_ric passata, effettuo la connessione e qui va in errore.

Private Sub UserForm_Activate()

' Visualizzazione sulla Listbox1 delle Tabelle utente
' le tabelle prese in considerazione sono solo quelle con i prefissi Tb_Azienda_XXXXXXX
' es. Tb_Azienda_Assimoco, Tb_Azienda_ICCREA_Stampe

Dim rs1 As ADODB.Recordset
Dim oConn As ADODB.Connection


Dim strSQL As String
Dim NLoop As Integer

strSQL = Strsql_Ric

MsgBox "frmRicerca -- UserFormActivate -- devo fare connessione"
GM_ConnMDB
On Error GoTo ErrorHandler

    NLoop = 0
    ListBox1.Clear
    ListBox1.RowSource = ""
    ListBox1.ColumnCount = Ncampi
    
    Set rs1 = oConn.Execute(Strsql_Ric)
    Do Until rs1.EOF
           Select Case NSel
                Case 1
                    ListBox1.AddItem rs1("Id") & vbTab                '"ROSSI" cognome in riga 1 colonna 1
                    ListBox1.List(NLoop, 1) = rs1("Utente")
                    ListBox1.List(NLoop, 2) = rs1("Intervento")
                    ListBox1.List(NLoop, 3) = rs1("D_Stato_Pratica")
'                Case 2
'                    ListBox1.AddItem rs1("ID_StatoRitiro") ' & vbTab                '"ROSSI" cognome in riga 1 colonna 1
'                    ListBox1.List(NLoop, 1) = rs1("D_StatoRitiro")
'                Case 3
'                ' da personalizzare
'                Case 4
'                ' da personalizzare
                Case Else
            End Select
    NLoop = NLoop + 1
    rs1.MoveNext
    Loop
    rs1.Close
    Set rs1 = Nothing
    
    If NLoop = 0 Then
        ListBox1.Clear
        ListBox1.RowSource = ""
        ListBox1.ColumnCount = 1
        ListBox1.AddItem "Nessun Record presente per la selezione Impostata"                '"ROSSI" cognome in riga 1 colonna 1
    End If
    
ErrorHandler:

    If Not oConn Is Nothing Then
    MsgBox "esco per --------------------> mancata connessione"
        If oConn.State = adStateOpen Then oConn.Close
    End If
    Set oConn = Nothing

    If Err <> 0 Then
        MsgBox Err.Source & "-->" & Err.Description, , "Error"
    End If

End Sub

daallo screenshot si vede che manca la connessione.

Non capisco perchè, dopo aver eseguito il metodo "GM_ConnMDB" in cui creo la connessione, esco per mancata connessione.
Potete aiutarmi ?
Sono in un errore bloccante.
Disponibile ad ogni chiarimento 

Grazie

Moreno

7 Risposte

  • Re: Perdita della connesione in navigazione pagine

    Credo che l'errore possa stare qui:

    Public Function GM_ConnMDB()
    
        Dim oConn As ADODB.Connection
        Dim rs As ADODB.Recordset
        Dim strSQL As String
        Dim PathUser As String

    Dichiari la oConn con scope all'interno della GM_ConnMDB, ma la dichiari anche come Pubblica e questo non va. Credo che il problema fondamentale sia proprio questo.
    Inoltre, la connessione al livello globale non è una buona idea, probabilmente è meglio realizzare una function che ti restituisca una connessione valida ogni volta che la invochi, la usi e poi la chiudi. In questo modo eviti che la connessione rimanga aperta senza motivo (con rischi di timeout) e, soprattutto, liberi risorse inutilmente utilizzate.

    Altra cosa:

        If Not oConn Is Nothing Then
        MsgBox "esco per --------------------> mancata connessione"
            If oConn.State = adStateOpen Then oConn.Close
        End If
        Set oConn = Nothing

    il MsgBox, viene mostrato (e di conseguenza la connessione chiusa) se la connessione è attiva!

    Il messaggio è fuorviante, nel senso che dice che esce per mancata connessione, ma in realtà il motivo per cui quel messaggio viene mostrato è perchè ESISTE una connessione attiva.

    Altro errore lo vedo dopo questa serie di istruzioni:

        If NLoop = 0 Then
            ListBox1.Clear
            ListBox1.RowSource = ""
            ListBox1.ColumnCount = 1
            ListBox1.AddItem "Nessun Record presente per la selezione Impostata"                '"ROSSI" cognome in riga 1 colonna 1
        End If

    Se ho capito bene NLoop rimane a zero se non ci sono record da mostrare sulla listbox e, fin qui, nulla di strano, il problema è che dopo queste righe, si dovrebbe chiudere la connessione (qualora non fosse più necessaria) ed uscire dalla routine esplicitamente con Exit Sub, evitando finire dentro la gestione degli errori.
    La part dopo ErrorHandler: andrebbe eseguita solo se è un errore che provoca il salto lì, altrimenti va evitata con l'Exit Sub

    TheTruster

  • Re: Perdita della connesione in navigazione pagine

    Grazie Truster per la tua cortese risposta.

    Ho cercato di correggere il codice in base alla tua osservazione.
    Non funziona.
    Cerco di riaggiornare il problema.

    la tua prima osservazione è:

    Dichiari la oConn con scope all'interno della GM_ConnMDB, ma la dichiari anche come Pubblica e questo non va. Credo che il problema fondamentale sia proprio questo.
    Inoltre, la connessione al livello globale non è una buona idea, probabilmente è meglio realizzare una function che ti restituisca una connessione valida ogni volta che la invochi, la usi e poi la chiudi. In questo modo eviti che la connessione rimanga aperta senza motivo (con rischi di timeout) e, soprattutto, liberi risorse inutilmente utilizzate.

    nel Modulo1 ho definito le variabili a livello globale e ho creato una sub (GM_ConnMDB) che mi restituisce la connessione

    ' Public oConn As ADODB.Connection
    Public rs1 As ADODB.Recordset
    Public strConn As String
    Public FieldKeyRic As Variant
    Public FieldoutRicerca As String
    Public Strsql_Ric As String
    Public NSel As Integer
    Public Ncampi As Integer
    Public SelezionatoCampodaElenco As Boolean
    Public NameClienteNew As String
    Public TipoSearch As String ' S=Selettiva G=Generica
    Public ArkSearch  As String  ' Archivio di ricerca  L=Località C=Clienti
    Public TipoArk  As String    ' D = Da Ritirare   R = Rilasciato
    Public DateKeyRic As Date
    Public txtChiamante As Integer  ' numero della txtbox chiamante per frmzoom
    Public UserLogged As Long    ' utente che si è loggato
    Public Commarea As String   ' salvo il txt chiamante tra frmritiro e frmCliente
    Public PathUser As String
    
    Public Function GM_ConnMDB()
    
    ' MsgBox "Effettuo la connessione"
    
        Dim oConn As ADODB.Connection
        Dim rs As ADODB.Recordset
        Dim strSQL As String
        Dim fld As Field  ' seconda versione
        Dim riga As Integer
        Dim PathUser As String
    
        Dim i As Integer
        
        ' PathUser = "C:\CorsoExcel\EcogestMarco\Ecogest\Madella.accdb;"    ' cambiare la cartella
    
          PathUser = ActiveWorkbook.Path & "\Covesap.accdb;"
          
    
        ' Specifica il percorso completo al tuo file .accdb
       
        strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & PathUser & "Persist Security Info=False;"
        
        ' Crea e apri la connessione
        Set oConn = New ADODB.Connection
        oConn.Open strConn
    
              MsgBox "Ho fatto GM_ConnMDB"
    
    End Function

    ho tolto dalla dichiarazione delle vaariabili pubbliche la oConn come indicato.

    Alla prima richiesta di lettura del db con il metodo btnConferma va in errore

    Private Sub btnConferma_Click()
    
    Dim oConn As ADODB.Connection
    Dim rs1 As ADODB.Recordset
    
    UserName = Me.TxtUserName
    Pwd = Me.txtPwd
    
    ' eseguo la connessione al MDB
      GM_ConnMDB
    
    ' MsgBox "sto controllando userName:  " & UserName
    
     If oConn.State = adStateOpen Then
             MsgBox "frmLogin ----- la connessione è attiva"
        Else
            MsgBox "frmlogin ------ la connessione non è attiva -----  esco"
            Exit Sub
        End If
    
    strSQL = "SELECT Utenti.User_Id_Utente, Utenti.Stato_Utente, Utenti.Password_Utente, Utenti.CognomeNome_Utente, Utenti.UserLevel, T_Profilo.D_UserLevel" & _
                 " FROM T_Profilo INNER JOIN Utenti ON T_Profilo.ID_UserLevel = Utenti.UserLevel " & _
                 " WHERE (((Utenti.User_Id_Utente)='Madella' and (Utenti.Password_Utente)= 'beatrice'))"
    
      
        Set rs1 = oConn.Execute(strSQL)
        If Not rs1.EOF Then
        
            Me.LabelUtente.Caption = rs1("CognomeNome_Utente")
            Application.Wait DateAdd("s", 2, Now)
            MsgBox " dopo la pausa di 2 secondi effettuo apertura di frmMain"
            frmMain.Show
            frmLogin.Hide
        Else
           
            Me.LabelUtente.Caption = " * Inesistente * "
        End If
    
     rs1.Close
     Set rs1 = Nothing
    
    
    
    End Sub
    

    nel metodo btnConferma uscendo da GM_ConnMDB la connessione deve essere in stato open. mentre va in errore sulla riga colorata in giallo.
    Errore evidenziato nello screnshot

    penso il problema stia in quasta situazione da risolvere.

    Grazie

    Moreno

  • Re: Perdita della connesione in navigazione pagine

    La questione principale è che utilizzi la stessa variabile, sia  al livello globale che al livello della routine. Questo crea certamente un conflitto.

    Quello che intendevo comunque, è creare una Function che si occupi soltanto di aprire una connessione e restuirtela pronta per usarla in una routine di tua scelta.

    Un esempio:

    Function GetDBConnection(dbPath As String) As ADODB.Connection
    
        Dim oConn As ADODB.Connection
        Dim strConn As String
    
    On Error GoTo Err_Handle
    
        strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath & ";Persist Security Info=False;"
        
        Set oConn = New ADODB.Connection
        oConn.Open strConn
        
        If Not oConn Is Nothing And oConn.State = adStateOpen Then
            Set GetDBConnection = oConn
            Exit Function
        End If
    
    Err_Handle:
        MsgBox "Impossibile stabilire la connessione col DB" & vbCrLf & Err.Description, vbCritical
    
    End Function

    Questa la usi molto semplicemente ogni volta che ti serve, dichiarando la variabile della connessione solo al livello locale (con scope di visibilità limitato alla routine in cui ti serve):

    Sub Operazioni_Sui_Dati()
    
    Dim myConn As ADODB.Connection
    Set myConn = GetDBConnection(ActiveWorkbook.Path & "\Covesap.accdb)
    
    '...
    '[eseguo tutte le operazioni che mi servono]
    '...
    
    myConn.Close
    Set myConn = Nothing
    
    End Sub

    Nella "Operazioni_Sui_Dati()" puoi ovviamente dichiarare tutti i recordset e le altre variabili necessarie per compiere tutto ciò che ti serve sul DB. Appena hai finito, chiudi la connessione e liberi le risorse.
    Se in un'altra routine ti servirà accedere nuovamente al DB, stessa cosa: Dichiari una variabile locale -> GetDBConnection -> Fai ciò che ti serve -> Chiudi.

    In questo modo minimizzi gli errori e sarai sicuro che, se la GetDBConnection andrà a buon fine (c'è un controllo di errori), allora la connessione è disponibile senza dubbio e puoi usarla senza testarla mille volte.

    TheTruster

  • Re: Perdita della connesione in navigazione pagine

    Ciao Truster

    Grazie per la pazienza.
    Ho fatto le correzzioni che mi hai cortesemente fornito, ma forse faccio ancora qualche errore sulle variabili locali o globali.
    Ti riassumo quanto fatto.
    sul modulo1 ho messo la function GetDBConnection

    Modulo1

    
    Function GetDBConnection(dbPath As String) As ADODB.Connection
    
        Dim oConn As ADODB.Connection
        Dim oRs As ADODB.Recordset
        Dim strConn As String
        Dim PathUser As String
    
    On Error GoTo Err_Handle
    
        strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath & ";Persist Security Info=False;"
        
        Set oConn = New ADODB.Connection
        oConn.Open strConn
        
        If Not oConn Is Nothing And oConn.State = adStateOpen Then
            Set GetDBConnection = oConn
            Exit Function
        End If
    
    Err_Handle:
        MsgBox "Impossibile stabilire la connessione col DB" & vbCrLf & Err.Description, vbCritical
    
    End Function

    nella form dove devo effettuare una lettura del db per popolare la form ho impostato il seguente codice

    Private Sub UserForm_Activate()
    
    ' Visualizzazione sulla Listbox1 delle Tabelle utente
    ' le tabelle prese in considerazione sono solo quelle con i prefissi Tb_Azienda_XXXXXXX
    ' es. Tb_Azienda_Assimoco, Tb_Azienda_ICCREA_Stampe
    
    
    Dim oConn As ADODB.Connection
    Dim rs1 As ADODB.Recordset
    
    
    Dim strSQL As String
    Dim NLoop As Integer
    
    strSQL = Commarea_Strsql
    Commarea_Strsql = ""
    
    MsgBox "frmRicerca -- UserFormActivate -- devo fare connessione"
    
    Set oConn = GetDBConnection(ActiveWorkbook.Path & "\Covesap.accdb")
    
    ' metto provvisoriamente questo test per verificare la esatta connessione
     If oConn.State = adStateOpen Then
             MsgBox "frmRicerca ----- la connessione è attiva"
        Else
            MsgBox "frmRicerca ------ la connessione non è attiva -----  esco"
            Exit Sub
        End If
    
        NLoop = 0
        ListBox1.Clear
        ListBox1.RowSource = ""
        ListBox1.ColumnCount = Ncampi  
         
            Set rs1 = oConn.Execute(strSQL)
            Do Until rs1.EOF
               Select Case NSel
                    Case 1
                        ListBox1.AddItem rs1("Id") & vbTab                '"ROSSI" cognome in riga 1 colonna 1
                        ListBox1.List(NLoop, 1) = rs1("Utente")
                        ListBox1.List(NLoop, 2) = rs1("Intervento")
                        ListBox1.List(NLoop, 3) = rs1("D_Stato_Pratica")
                 
                    Case 2
                        ListBox1.AddItem rs1("ID_StatoRitiro") ' & vbTab                '"ROSSI" cognome in riga 1 colonna 1
                        ListBox1.List(NLoop, 1) = rs1("D_StatoRitiro")
    
                    Case Else
                End Select
        NLoop = NLoop + 1
        rs1.MoveNext
        Loop
        
        rs1.Close
        Set rs1 = Nothing
        oConn.close
        set oConn = nothing
        
        If NLoop = 0 Then
            ListBox1.Clear
            ListBox1.RowSource = ""
            ListBox1.ColumnCount = 1
            ListBox1.AddItem "Nessun Record presente per la selezione Impostata"                '"ROSSI" cognome in riga 1 colonna 1
        End If
     
     Exit Sub
    

    va ancora in errore 

    mi rendo conto di disturbare, ma mi sembra di aver rispettato le tue indicazioni.

    Sicuramente in maniera non corretta.
    Scusa e grazie

    Moreno

  • Re: Perdita della connesione in navigazione pagine

    Dovresti specificare dove va in errore.

    Suppongo che  da qui:

     If oConn.State = adStateOpen Then
             MsgBox "frmRicerca ----- la connessione è attiva"
        Else
            MsgBox "frmRicerca ------ la connessione non è attiva -----  esco"
            Exit Sub
        End If

    Passi indenne, altrimenti avresti avuto il msgbox della connessione non attiva.

    Se hai un errore, probabilmente è nella query che cerchi di usare e che non mostri, visto che alla variabile  strSQL viene assegnato il valore di Commarea_Strsql

    strSQL = Commarea_Strsql
    Commarea_Strsql = ""

    Tral'altro Commarea_Strsql non è dichiarata al livello di routine, quindi suppongo sia al livello globale (pessima idea) e in questo caso, non si capisce perchè venga cancellata dopo averla assegnata alla strSQL! Potrebbe essere usata direttamente, no?

    In ogni caso, quello che ottieni sembra un errore dovuto ad una query errata (molto probabilmente il nome di un campo errato), ma se non la mostri non so cos'altro dire.

    Edit:

    Private Sub btnConferma_Click()
    
    Dim oConn As ADODB.Connection
    Dim rs1 As ADODB.Recordset

    Ho visto che nella routine sopra usi ancora oConn. Questa volta non dovrebbe essere un problema, se hai tolto la variabile globale, ma per chiarezza e soprattutto per coerenza, ti consiglio di chiamare la variabile diversamente, myConn, ad esempio, come ho fatto io. Altrimenti potresti fraintendere la variabile ed il suo utilizzo.

    TheTruster

  • Re: Perdita della connesione in navigazione pagine

    Ciao Truster

    ti ringrazio dei suggerimenti davvero efficaci.

    Nel tuo ultimo post ponevi che il problema fosse da individuare in un errore della query.

    Se hai un errore, probabilmente è nella query che cerchi di usare e che non mostri, visto che alla variabile  strSQL viene assegnato il valore di Commarea_Strsql

    Avevi davvero ragione. Non mi ero accorto di un errore nella query.
    Sistemato quello funziona  a meraviglia

    Ti ringrazio per la pazienza e la cortesia.

    Ciao
    Moreno

  • Re: Perdita della connesione in navigazione pagine

    Grazie per il riscontro.

    TheTruster

Devi accedere o registrarti per scrivere nel forum
7 risposte