[Parte 1Parte 2Parte 3Parte 4Parte 5]


Accesso ai dati in VB
Di:Enrico Granata



Uno dei maggiori punti di forza di VB Φ di sicuro il motore di accesso ai dati Jet che condivide con Microsoft Access In questa breve serie di articoli vorrei dare al lettore delle linee guida per l'utilizzo proficuo dei principali elementi di Jet

Se ci serve un Database...

...possiamo fare 2 cose: aprirlo o crearlo

La differenza sostanziale sta nel fatto che se il file esiste lo apriamo, altrimenti lo creiamo

Ad esempio aprire il file "MioDb.Mdb" richiede

Dim MioDatabase As Database

Set MioDatabase=DbEngine.WorkSpaces(0).OpenDatabase("MioDb.Mdb")

o la forma abbreviata

Dim MioDatabase As Database

Set MioDatabase=OpenDatabase("MioDb.Mdb")

Cosa significhi tutto questo codice lo capiremo adesso

La struttura di Jet ci aiuta sempre

Il motore Jet è fortemente OO(Object Oriented) nel senso che la sua struttura è orientata agli oggetti, il che ci obbligherà a memorizzare qualche informazione sugli oggetti che compongono Jet

In seguito poi saremo addirittura facilitati da questa scelta di Microsoft

Il primo oggetto che rappresenta l'istanza di Jet in esecuzione è anche uno di quelli meno usati e prende il nome di

DbEngine

Questo oggetto ha sulle spalle tutta la gerarchia di Jet Engine, ma è anche uno di quegli oggetti che lavorano nell'ombra, tanto è che nonostante le due versioni del codice riportato sopra siano equivalenti di solito vedrete sempre la seconda o al limite l'indicazione del solo WorkSpace

Ma anche lui ha diritto al suo momento di gloria, che arriva sempre nei momenti difficili, come quando usate RepairDatabase()

DBEngine.RepairDatabase "MioDb.Mdb"

Questo metodo tenta di ripristinare un Database danneggiato di nome MioDb.Mdb

Questo metodo si usa però solo di rado, un metodo più usato è CompactDatabase()

DBEngine.CompactDatabase "MioDb.Mdb", "MioNuovoDb.Mdb"

Questo metodo compatta il file "MioDb.Mdb" e lo copia in "MioNuovoDb.Mdb", per ottenere "MioDb.Mdb" compattato è necessario usare anche

Kill "MioDb.Mdb"

FileCopy "MioNuovoDb.Mdb","MioDb.Mdb"

Compattare un Database permette di eliminare fisicamente i record eliminati che vengono marcati da Jet con un segnaposto, ma questo è un metodo di Recordset

Un altro metodo di DbEngine utile in ambienti multiutente è CreateWorkSpace()

Dim MyWorkSpace As WorkSpace

Set MyWorkSpace = CreateWorkspace("NuovoWorkSpace", "Enrico", "JetEngine")

Il WorkSpace è un ambiente di transazioni per un utente, ove con transazioni si intende qualsiasi processo che faccia uso delle funzionalità di Jet Engine

Il nostro codice crea un WorkSpace chiamato NuovoWorkSpace il cui utente è Enrico con password JetEngine

Siamo quasi alla fine di questa trattazione di DbEngine, ma mancano ancora due metodi, Idle() e RegisterDatabase(), oggi però ci soffermeremo su Idle()

DBEngine.Idle

Supponiamo che dopo un pò di tempo che elaborate dati notiate un rallentamento nel sistema, provate a chiamare Idle() e dovreste notare un miglioramento dell'esecuzione perchè Idle() permette a Jet di completare alcune operazioni interne

Dim JetVersion As String, NumVersion As String, NumRelease As String

Dim DotLocation As Integer

JetVersion = DBEngine.Version

DotLocation = InStr(JetVersion, ".")

NumVersion = Left$(JetVersion, DotLocation - 1)

NumRelease = Right$(JetVersion, Len(JetVersion) - DotLocation)

Debug.Print "Versione di Jet:" & NumVersion & "." & NumRelase

Prima di iniziare la disamina sui Database vorrei spiegare questo pezzo di codice che reperisce Versione e Aggiornamento di Jet Engine tramite DbEngine.Version il quale restitiusce una stringa del tipo Version.Relase(5.21 indica la Versione 5, Aggiornamento 21) e lo stampa nella finestra Debug

DbEngine.WorkSpaces(0).Databases(0).OpenRecordset("Varie"), ovvero?

Ovvero apri la Tabella Varie dell'elemento 0 dell'insieme Databases, dell'elemento 0 dell'insieme WorkSpaces dell'oggetto DbEngine, so che è un pò difficile, ma andiamo con ordine e capiremo tutto

Nella gerarchia di Jet Database discende da WorkSpace che discende da DbEngine, ma Jet prevede che tutti gli oggetti, all'infuori di DbEngine, abbiano anche un insieme che ne contiene tutte le istanze, così DbEngine.WorkSpace prevede l'insieme DbEngine.WorkSpaces che conterrà tutti i WorkSpace

Quindi DbEngine.WorkSpace.Database prevede DbEngine.WorkSpaces(ind).Databases

Ma di solito gli insiemi non ci saranno troppo utili, pertanto questa trattazione sugli insiemi sarà ripresa poche volte

Set oggettodb = areadilavoro.OpenDatabase(nomedb[, esclusivo[, solalettura[, fonte]]])

Questa è la sintassi completa di WorkSpace.OpenDatabase(), metodo che ritorna un oggetto di tipo Database

Di solito però non tutti gli elementi della sintassi sono utili, noi comunque passiamoli in rassegna

nomedb

E' il nostro Database, questo può essere un nome di file o un DSN ODBC, in tal caso dobbiamo specificare tutti i parametri

esclusivo

Utile solo in ambienti multiutenti, dice a Jet che vogliamo impedire ad altri utenti l'accesso al DB

solalettura

Dice a Jet che vogliamo aprire il Database in sola lettura, ovvero solo per leggere dati

fonte

Indica la stringa di connessione ODBC, se lo si usa bisogna specificare anche esclusivo e solalettura

Un esempio potrebbe essere questo:

Set MyDb = MyWorkSpace.OpenDatabase("", True, False, "ODBC;")

Questo permetterà all'utente di scegliere tra tutti i DSN ODBC in una finestra di dialogo visualizzata da ODBC

Per i più pignoli riporto qui la sintassi del parametro Fonte con un DSN ODBC

"ODBC;

UID=utente; PWD=password;

DSN=nomefontedati

LOGINTIMEOUT=secondi"

che potrebbe generare qualcosa come

"ODBC;

UID=Enrico; PWD=JetEngine;

DSN=MioDatabase;

LOGINTIMEOUT=50"

cioè, l'utente Enrico con password JetEngine richiede di apire MioDatabase con LoginTimeout di 50 secondi

Tornando a VB possiamo ora passare al metodo successivo: CreateDatabase(), se ricordate lo accennammo all'inizio dell'articolo e dicemmo che ci sarebbe servito nel caso il Database non fosse esistito, adesso poniamo che noi abbiamo bisogno di un database di nome "miofirst.mdb", il file manca, come crearlo?

Set MioDb = CreateDatabase ("miofirst.mdb", dbLangGeneral)

Ovvero assegna a MioDb il file miofirst.mdb che deve usare l'ordinamento generico, valido per l'Italiano e per altre lingue quali Inglese, Tedesco, Francese, Portoghese e Spagnolo

il che vuol dire che nella maggioranza dei casi useremo dbLangGeneral, ma esistono altre costanti che potete cercare nella guida di VB

Ma questo non esaurisce le operazioni da compiere nel nostro esempio, prima però vorrei discutere su un metodo importante, CreateRelation()

Set MyRelation = MyDb.CreateRelation("MiaRelazione", "Impiegati", "CassaIntegrati")

Questo metodo crea una relazione tra Impiegati e CassaIntegrati, ma c'è ancora qualcosa da fare, decidere quali campi saranno coinvolti nella relazione

Set MyField = MyRelation.CreateField("CodiceImpiegato")

MyField.ForeignName = "CodiceCassaIntegrato"

MyRelation.Fields.Append MyField

che mette in relazione Impiegati.CodiceImpiegato con CassaIntegrati.CodiceCassaIntegrato e infine aggiunge a MyRelation.Fields che è un insieme di oggetti di tipo Field, cioè campo

Comunque ci manca ancora una cosa per completare la nostra Relation, cioè

MyDb.Relations.Append MyRelation

che inserisce nell'insieme Relations di MyDb la nostra Relation

Questo argomento ci sposta verso l'argomento Field, ma questo sarà argomento del prossimo articolo, adesso vorrei trattare un altro metodo interessante di Database MakeReplica() il quale crea Repliche di un Database, ma questo richiede una modifica al Database, cioè questa:

MyDb.Replicable=True

che rende il Database replicabile, ma attenti, non provate dopo a scrivere

MyDb.Replicable=False

perchè questo genererebbe un errore di Run Time, una volta che Replicable è True non può più diventare False

Una volta settato Replicable è però possibile usare MakeReplica() per copiare un DB

MyDb.MakeReplica("A:\back10marzo1998.mdb")

potrebbe essere usato per creare la copia di Backup del 10 marzo 1998 del Database MyDb, l'utilità è chiara, poter creare copie identiche di un Database senza bisogno di FileCopy e quindi della determinazione del nome di file che in applicazioni come Data Manager, ove il DB non è determinato dal programma, può richiedere la dichiarazioni di ulteriori variabili, come nell'esempio che segue

Dim DatabaseName As String

...

CommonDialog1.ShowOpen

DatabaseName=CommonDialog1.filename

Set MyDb=OpenDatabase(DatabaseName)

...

Public Sub SaveCopy()

Dim DbNew As String

CommonDialog1.ShowOpen

DbNew=CommonDialog1.filename

Set MyDb=Nothing 'Sempre meglio chiudere

FileCopy DatabaseName, DbNew

Set MyDb=OpenDatabase(DatabaseName) 'Ora possiamo riaprire

End Sub

che imposta DatabaseName con il nome del Database così che la chiamata di SaveCopy possa funzionare, un elemento di rilievo sono i commenti di SaveCopy() che dicono

'Sempre meglio chiudere

nel senso che prima di queste transazioni è sempre meglio chiudere il Database per evitare problemi

poi dopo

'Ora possiamo riaprire

perchè adesso Jet può riprendere il controllo del DB, e questo è forse il punto di forza di MakeReplica() di Jet rispetto alla nostra SaveCopy(), MakeReplica() non deve chiudere il DB e questo ci fa risparmiare notevole tempo, pertanto ecco la stessa versione del codice con MakeReplica()

CommonDialog1.ShowOpen

Set MyDb=OpenDatabase(CommonDialog1.filename)

MyDb.Replicable=True

...

Public Sub SaveCopy()

Dim DbNew As String

CommonDialog1.ShowOpen

DbNew=CommonDialog1.filename

MyDb.MakeReplica(DbNew) 'Qui non dobbiamo chiudere nè fare altro

End Sub

come si può notare il codice è più breve e quindi anche più veloce

Per questa volta abbiamo comunque concluso la nostra esplorazione di Jet