Stavolta approfondiremo l'oggetto Container e Document
MyDb.Containers("Databases").UserName="MeMedesimo"
MyDb.Containers("Databases").Permissions=dbSecReadSec 'Leggi le impostazioni di sicurezza
Con questo codice l'utente MeMedesimo avrà il permesso di leggere le impostazioni di sicurezza, ma non di modificarle
Se poi vogliamo invece attribuire allo stesso MeMedesimo permessi di lettura di una tabella di nome MyTable
MyDb.Containsers("Tables").Documents("MyTables").UserName="MeMedesimo"
MyDb.Containsers("Tables").Documents("MyTables").Permissions=dbSecRetreiveData
L'organizzazione di sicurezza è divisa in Containers e Documents, ove Containers(stringa1).Documents(stringa2) identifica l'oggetto di nome stringa2 del Container stringa1
Praticamente questo è tutto ciò che c'è da dire sulla sicurezza di Jet, sembra difficile, ma consultando la guida di VB che è un riferimento completo all'argomento e che contiene anche tutte le costanti dbSec sarà più facile
Ricordate che qualche mese fa non sapevate neanche cosa fosse un oggetto Database e oggi siete arrivati alla loro sicurezza in ambienti multiutente
Passiamo quindi ad un altro argomento importante, ma meno noto, le Query con Parametri
Query variabili
Queste sono query particolari in cui alcuni valori non sono noti a priori, ma lo saranno in un secondo tempo, ad esempio in un ipotetico programma per gestire un database di una Città si potrebbe voler rimuovere tutti i record dove AnnoMorte è < 1990, ma il programma dispone solo della funzione "Rimuovi record per Anno di Morte", cioè della routine RemoveForDeathYear()
Public Sub RemoveForDeathYear()
End Sub
Voi potreste dire che non c'è bisogno delle query con parametri, basta usare l'operatore & come nel seguente esempio
Dim DeathYear As String
DeathYear=InputBox("Anno di morte")
Dim SQLQuery As String
SQLQuery="DELETE FROM Anagrafe WHERE AnnoMorte<" & DeathYear
Ma perchè fare così quando esiste una query che fa esattamente la stessa cosa?
PARAMETERS DeathYear Text; DELETE FROM Anagrafe WHERE AnnoMorte<DeathYear
L'unica cosa che questa query ha di insolito è la sezione prima del ; cioè "PARAMETERS DeathYear Text" che non fa altro che definire un parametro DeathYear che poi verrà modificato in fase di esecuzione
Prima di definire RemoveForDeathYear() dobbiamo però definire la CreateSQLQueryDefs() che nel nostro caso creerà la query con parametri
Public Sub CreateSQLQueryDefs()
Dim Query As QueryDef
Set Query=MyDb.CreateQueryDef("RemoveDeath", "PARAMETERS DeathYear Text; DELETE FROM Anagrafe WHERE AnnoMorte<DeathYear")
End Sub
Tutto è pronto per la RemoveForDeathYear() la quale grazie ai QueryDef sarà molto ristretta
Diciamo che possiamo usare in questo caso QueryDef.ExecuteSQL per ottenere il numero di righe eliminate
Public Sub RemoveForDeathYear()
Dim DeathYear As String
DeathYear=InputBox("Anno di morte")
Dim SQLQuery As QueryDef
Set SQLQuery=MyDb.QueryDefs("RemoveDeath")
SQLQuery.Parameters("DeathYear")=DeathYear
Dim NLines As Long
NLines=SQLQuery.ExecuteSQL
MsgBox NLines & " linee influenzate dall'esecuzione della Query", 64, "Informazione"
End Sub
La routine non fa altro che completare la QueryDef RemoveDeath e poi esegue con ExecuteSQL che come dicemmo nei mesi passati ritorna un Long che corrisponde al numero di Linee sulle quali la Query ha operato
Alla fine mostriamo in una MsgBox il Long ritornato e anche l'argomento
A questo punto le nostre conoscenze di Jet sono molto vaste, ci manca solo una cosa, cioè una verifica delle nostre conoscenze di Jet che potremo eseguire nello spazio rimasto in questo articolo e nel successivo, cioè creare un file di utilità generale per gestire un Database, esso non sarà un .cls, ma un .bas, così da poterlo utilizzare con Database diversi senza problemi di istanze
Rem dbMan.bas
Rem Gestore di Jet Engine
'Questa Function crea un Database
Public Function CreateDB(WorkSpace As WorkSpace,Name As String) As Database
Set CreateDB=WorkSpace.CreateDatabase(Name, dbLangGeneral)
End Function
Questa Function ritorna un oggetto Database corrispondente ad un Database creato con locale settato a dbLangGeneral nel WorkSpace e con il nome da noi voluto
La seconda Function invece apre un Database
'Questa Function apre un Database
Public Function OpenDB(WorkSpace As WorkSpace,Name As String) As Database
Set OpenDB=WorkSpace.OpenDatabase(Name)
End Function
Diciamo che queste funzioni sono molto semplicistiche, poichè omettono molti parametri nella dichiarazione, ma come esempio di uso di Jet bastano e nel caso vi serva un codice più approfondito potete sempre crearlo, in fondo siamo arrivati alla fine della serie, o no?
'Questa Function instanzia un TableDef
Public Function CreateNewTableDef(Database As Database, Name As String) As TableDef
Set CreateNewTableDef=Database.CreateTableDef(Name)
End Function
E' ovvio che la routine di creazione dei record la prenderemo dalla 2░ lezione, dove ne implementammo una versione
Public Sub AggiungiCampo(Tabella As TableDef, Nome _
As String, TipoDati As Integer, Optional Dimensione)
Dim MyField As Field
If IsMissing(Dimensione) Then
Set MyField=Tabella.CreateField(Nome, TipoDati)
Else
Set MyField=Tabella.CreateField(Nome, TipoDati, Dimensione)
End If
Tabella.Fields.Append MyField
End Sub
Questa è una prima parte della nostra dbMan.Bas che dovrebbe facilitarci la vita nell'uso di Jet
Ovviamente le routine come AppendTableDef() non vengono implementate qui poichè sono troppo facili, ma per aiutarvi ne implemento una, proprio la AppendTableDef()
'Questa Sub esegue l'Append su un TableDef
Public Sub AppendTableDef(Database As Database, Table As TableDef)
Database.TableDefs.Append Table
End Function
Praticamente queste sono le basi, per creare un QueryDef esiste una routine ancora più facile da implementare, che però fornirò io poichè questo fa parte del lavoro di scrittura di questa serie di articoli
'Questa Function ritorna un QueryDef valido
Public Function CreateNewQueryDef(Database As Database,Name As String, SQL As String) As QueryDef
Set CreateNewQueryDef=Database.CreateQueryDef(Name, SQL)
End Function
Per eseguire una query che non ritorna valori ci vorranno invece 2 routine, una per Execute e una per ExecuteSQL
Se ricordate la differenza Execute non ritorna nulla, ExecuteSQL il numero di righe interessate dalla query
'Gestione delle Query che non ritornano Recordset
Public Sub ExecuteQuery(Database As Database, SQL As String)
Database.Execute SQL
End Sub
Public Function ExecuteSQLQuery(Database As Database, SQL As String) As Long
ExecuteSQLQuery=Database.ExecuteSQL SQL
End Function
Anche su queste 2 funzioni c'è poco da dire, una è una Sub che usa Execute, un' altra è una Function che usa ExecuteSQL, per costruire i nomi è stato usato il nome del metodo seguito da Query
Esiste poi la gestione dei RecordSet che implementeremo in queste funzioni
Public Function OpenTable(Database As Database, Name As String) As RecordSet
Set OpenTable=Database.OpenRecordSet(Name)
End Function
Public Sub MoveToFirstRecord(RecordSet As Recordset)
RecordSet.MoveFirst
End Sub
Public Sub MoveToLastRecord(RecordSet As Recordset)
RecordSet.MoveLast
End Sub
Public Sub MoveToNextRecord(RecordSet As Recordset)
If Not RecordSet.Eof Then RecordSet.MoveNext
End Sub
Public Sub MoveToPreviousRecord(RecordSet As Recordset)
RecordSet.MovePrevious
End Sub
Questo è però solo l'inizio della gestione dei RecordSet che però lascio a voi in quanto nell'ultimo articolo ripasseremo tutto ciò che abbiamo imparato
Tanto per iniziare vi ricordo di implementare tutti i metodi Find e il metodo Clone(), oltre al metodo Close()
Poi ricordate CompactDatabase() e RepairDatabase() che possono sempre tornare utili, ah...infine MakeReplica() che potete usare dopo CompactDatabase(), anche se in quel contesto io preferisco Kill() e FileCopy()
Dovete poi ricordare di fornire una piattaforma stabile per dbMan, quindi cercate tutti gli errori di accesso ai dati nella guida di VB e verificate in quali casi dovreste inserirli nella Errors-Catching routine
Se siete ambiziosi ricordate che un DBMS si può realizzare in VB, certo, Access sarà sempre Access, ma un programma come VisData è già un valido DBMS di dimensioni ridotte, nonostante il numero di file che lo compongono, cose da includere in un DBMS sono praticamente tutte quelle che abbiamo studiato