none
VB.net determinare se un database Access 2007 è corrotto (anche parzialmente) RRS feed

  • Domanda

  • Mi si è presentato un problema: ho un programmino in vb.net che si occupa di lanciare un db in formato .mdb tramite Access 2007 tra gli altri controlli che esegue il programma in questione c'è un grezzo check dell'integrità del database:

    Using cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data source=" & strPath & "\" & strDb & ";")
                Try
                    cn.Open()
                    cn.Close()
                    Return True
                Catch ex As Exception
                    'cn.Close()
                    Return False
                End Try
    
    End Using

    Se non riesce a connettersi al db vuol dire che questo è danneggiato, quindi segnala la cosa.

    Il problema è sorto con un db parzialmente corrotto: la maschera principale non funziona più però ci si connette al db regolarmente e, aprendolo tramite Access non visualizza la maschera incriminata, però non segnala errori. Con una compattazione il db è tornato a funzionare e poi di nuovo lo stesso errore, finchè non è stato sostituito con una copia "pulita".

    Mi chiedo se è possibile tramite VB.NET determinare se un db Access è corrotto parzialmente, chiaramente senza stare troppo tempo ad eseguire controlli. Avevo trovato queste informazioni:

    “L'unico momento in cui Access, o meglio il Jet, fa un check di integrità è durante la fase di import/export degli oggetti. Quindi se vuoi controllare ed essere ragionevolmente certo che il db non è corrotto, dovresti creare un db nuovo e in quello cercare di importare gli oggetti dal db originale. Se un oggetto (tabella, query, relazione, form, report modulo, macro, ec..) è corrotto, il Jet ti ritorna un errore...”

    A parte che parlano dal lato Access e non VB, comunque andare a testare in questo modo un db sarebbe troppo pesante in termini di tempo necessario (esportare tutte le form, report, moduli.... in un db temporaneo che poi dovrebbe essere eliminato)

    venerdì 3 ottobre 2014 06:21

Risposte

  • Ciao Roberto_6,

    non sollevandoti nessuna eccezione non credo tu riesca a identificare una corruzione parziale del DB.

    Potresti lanciare una ricostruzione prima di accedere al DB (se questo non interferisce con altri utilizzatori del DB)

    HOW TO: Comprimere un database di Microsoft Access Database con Visual Basic .NET

    personalmente però cercherei i motivi di tale corruzione.

    Ciao


    Renato Marzaro  MVP Visual Basic

    http://community.visual-basic.it/renato

    venerdì 3 ottobre 2014 07:30
    Moderatore
  • Ciao Roberto_6,

    in linea generale, per verificare la bontà di un file, è consigliabile testarne l'hash rispetto ad un modello precedentemente ritenuto corretto. VB mette a disposizione diverse classi di hashing, nell'esempio che ti propongo viene utilizzato l'algoritmo SHA256.

    Dim s As New System.Security.Cryptography.SHA256Managed
    Dim fileBytes() As Byte = IO.File.ReadAllBytes("c:\tmp\words.db")
    Dim hash() As Byte = s.ComputeHash(fileBytes)
    Dim hashConfronto As String = "a529d544ea399f76f64891367f67489c10ea8c55ad4e777e89b0ed866e560e17"
    Dim hashCalcolato As String = ByteArrayToString(hash)
    MsgBox(hashCalcolato = hashConfronto)
    
    ' Abilitando questa riga, si vede l'hash del file "originale"
    ' MsgBox(hashCalcolato)

    Utilizzando la funzione di appoggio:

        Private Function ByteArrayToString(ByVal arrInput() As Byte) As String
            Dim sb As New System.Text.StringBuilder(arrInput.Length * 2)
            For i As Integer = 0 To arrInput.Length - 1
                sb.Append(arrInput(i).ToString("X2"))
            Next
            Return sb.ToString().ToLower
        End Function

    In sostanza, viene aperto il file, letti tutti i bytes che lo compongono, e calcolata la stringa univoca corrispondente. Una volta calcolata, la dovrai memorizzare in una variabile stringa (nell'esempio hashConfronto), e - ad ogni avvio - far rieseguire la verifica sul tuo file, per poi controllare se l'hash calcolato è uguale al tuo.

    Spero di esserti stato di aiuto

    Nota: ovviamente questo metodo è consigliabile su files di dimensioni "ragionevoli". Dovendo leggere e memorizzare temporaneamente i bytes che lo compongono, va da sé che le performances decadrebbero drasticamente in presenza di files molto grandi. In quella situazione, si potrebbe comunque pensare ad un approccio di questo tipo, ma frazionando l'elaborazione.



    Emiliano Musso


    venerdì 3 ottobre 2014 07:17
    Moderatore

Tutte le risposte

  • Ciao Roberto_6,

    in linea generale, per verificare la bontà di un file, è consigliabile testarne l'hash rispetto ad un modello precedentemente ritenuto corretto. VB mette a disposizione diverse classi di hashing, nell'esempio che ti propongo viene utilizzato l'algoritmo SHA256.

    Dim s As New System.Security.Cryptography.SHA256Managed
    Dim fileBytes() As Byte = IO.File.ReadAllBytes("c:\tmp\words.db")
    Dim hash() As Byte = s.ComputeHash(fileBytes)
    Dim hashConfronto As String = "a529d544ea399f76f64891367f67489c10ea8c55ad4e777e89b0ed866e560e17"
    Dim hashCalcolato As String = ByteArrayToString(hash)
    MsgBox(hashCalcolato = hashConfronto)
    
    ' Abilitando questa riga, si vede l'hash del file "originale"
    ' MsgBox(hashCalcolato)

    Utilizzando la funzione di appoggio:

        Private Function ByteArrayToString(ByVal arrInput() As Byte) As String
            Dim sb As New System.Text.StringBuilder(arrInput.Length * 2)
            For i As Integer = 0 To arrInput.Length - 1
                sb.Append(arrInput(i).ToString("X2"))
            Next
            Return sb.ToString().ToLower
        End Function

    In sostanza, viene aperto il file, letti tutti i bytes che lo compongono, e calcolata la stringa univoca corrispondente. Una volta calcolata, la dovrai memorizzare in una variabile stringa (nell'esempio hashConfronto), e - ad ogni avvio - far rieseguire la verifica sul tuo file, per poi controllare se l'hash calcolato è uguale al tuo.

    Spero di esserti stato di aiuto

    Nota: ovviamente questo metodo è consigliabile su files di dimensioni "ragionevoli". Dovendo leggere e memorizzare temporaneamente i bytes che lo compongono, va da sé che le performances decadrebbero drasticamente in presenza di files molto grandi. In quella situazione, si potrebbe comunque pensare ad un approccio di questo tipo, ma frazionando l'elaborazione.



    Emiliano Musso


    venerdì 3 ottobre 2014 07:17
    Moderatore
  • Ciao Roberto_6,

    non sollevandoti nessuna eccezione non credo tu riesca a identificare una corruzione parziale del DB.

    Potresti lanciare una ricostruzione prima di accedere al DB (se questo non interferisce con altri utilizzatori del DB)

    HOW TO: Comprimere un database di Microsoft Access Database con Visual Basic .NET

    personalmente però cercherei i motivi di tale corruzione.

    Ciao


    Renato Marzaro  MVP Visual Basic

    http://community.visual-basic.it/renato

    venerdì 3 ottobre 2014 07:30
    Moderatore
  • Ho testato il metodo dell' HASH, però purtroppo non può essere utilizzato perchè Access modifica il file mdb ad ogni accesso: semplicemente aprendo il db con Access 2007 e richiudendolo, senza quindi eseguirvi operazioni l'hash è cambiato così come le dimensioni del file. Probabilmente Access va a modificare le sue tabelle di sistema tipo msys.....

    Le dimensioni del database inizialmente sono contenute: circa 15 Mb; però con l'uso arriva presto a 50 Mb probabilmente a causa delle query che vengono mandate in esecuzione durante l'utilizzo.

    Il motivo della corruzione può essere una chiusura forzata del db.

    Volevo evitare di compattare il db, ad ogni apertura, ma mi stò rendendo conto che sembra non ci siano metodi leggeri per verificare l'integrità di un db Access parzialmente corrotto

    venerdì 3 ottobre 2014 12:29
  • Sì, ovviamente un database cambia la propria struttura con l'utilizzo, quindi l'hash si altera di conseguenza. Ipotizzando che la corruzione del file avvenga a programma chiuso (altrimenti il problema è da ricercarsi altrove), potresti calcolare l'hash di confronto in chiusura programma (e salvarlo da qualche parte: file di testo, chiave di registro, ecc.), ed utilizzarlo al successivo riavvio, per verificare se - tra un utilizzo e l'altro - siano state apportate modifiche esternamente al tuo applicativo.

    Emiliano Musso MVP Visual Basic

    venerdì 3 ottobre 2014 12:45
    Moderatore
  • Si potrebbe essere una soluzione (a volte ci giro intorno pur avendo la soluzione sotto gli occhi)
    venerdì 3 ottobre 2014 13:30
  • ciao Roberto_6,

    Ma al DB chi accede ?

    Solo la tua applicazione ? (Non credo altrimenti non capisco il discorso dei Form all'interno del DB)

    Quante istanze della tua applicazione ? quante esterne ?

    Ciao


    Renato Marzaro  MVP Visual Basic

    http://community.visual-basic.it/renato

    venerdì 3 ottobre 2014 15:54
    Moderatore
  • L'applicazione viene utilizzata dall'utente generico sul proprio computer (si tratta della parte Front quindi contiene Query, Maschere, Report, Codice) in caso il programma la trovi ol db Front corrotto copia dal computer che fa da file-server una versione funzionante del db sovrascrivendo la copia corrotta.

    Ho pensato un pò al sistema dell'hash, però non penso sia applicabile perchè può capitare che il db si corrompa in fase di utilizzo da parte dell'utente, quindi se calcolo l'hash a db chiuso può essere che esegua quest'operazione su un db che si è già corrotto. Finora la corruzione se si verificava era tale da essere intercettata in fase di connessione al db, però è capitata una sorta di corruzione parziale, tale da non essere individuata.

    lunedì 6 ottobre 2014 12:04
  • Ciao Roberto_6,

    personalmente mi preoccuperei molto di un DB Access che continua a corrompersi ... prima o poi perderai sicuramente dei dati :(

    Perché non pensare ad una soluzione con LightSwitch e SQL Express o mantenere MDB ma appoggiare i dati su SQL ?

    Ciao


    Renato Marzaro  MVP Visual Basic

    http://community.visual-basic.it/renato

    lunedì 6 ottobre 2014 18:41
    Moderatore
  • Trattandosi di un Front non c'è da preoccuparsi, visto che non contiene dati, se si corrompe viene sostituito con una copia pulita.

    Trattandosi di Access, sopratutto versioni successive alla 97 ho constatato che la corruzione dei db è all'ordine del giorno.

    Il passaggio ad altro dbms è già preventivato, però nel frattempo dobbiamo accontentarci di Access.

    giovedì 9 ottobre 2014 07:05