Accesso ai dati con DAO e MFC |
Home Page | Commenti | Articoli | Faq | Documenti | Ricerca | Archivio | Storie dalla Sala Macchine | Contribuire | Imposta lingua:en it | Login/Register
L'accesso e la manipolazione dei database sono una delle attivita' "normali" per quasi qualunque programma, non conta tanto cosa il programma fa', in un modo o nell'altro una delle sue attivita' sara' quella di accedere a dei file per scrivere o leggere delle informazioni che dovranno poi essere rilette in seguito.
Una delle funzionalita' principale dei database e' per l'appunto quella di memorizzare le informazioni in modo che sia rapido ritrovarle in seguito.
Pochi sistemi pero' hanno questo conecetto di "database" cosi' pervasivo (l'AS 400 per esempio, per cui ogni file ha una struttura di record). In generale i programmi possono salvare le informazioni in molti modi diversi e leggerle in molti modi diversi.
Per accedere ad un database (di qualunque tipo) in ambiente Windows vi sono svariati modi. Il principale e' quello di utilizzare l'interfaccia generica di ODBC, che consente l'accesso ad un qualunque database per cui e' presente un driver di interfaccia.
ODBC e' un ottimo sistema di accesso, se non che le sue API di comunicazione sono piuttosto complesse, e non sono idonee per l'accesso tramite linguaggi come ASP o Visual Basic. Per ovviare a questo problema la Microsoft ha sviluppato ADO, Activex Data Object, che, come dice il nome, e' un componente di tipo ActiveX che consente l'accesso ai dati tramite interfaccia ad oggetti. Essendo un componente ActiveX, la sua interfaccia viene "esposta" tramite l'accesso ad oggetti di default. Quindi e' ottimo per il collegamento tramite Visual Basic ed altri linguaggi simili.
Per consentire un accesso ai dati anche in modo "remoto", Microsoft ha poi sviluppato l'interfaccia OLE DB, che consente un accesso diretto ai database mediante una serie di oggetti che possono essere richiamati e pilotati mediante OLE. Purtroppo l'OLE non e' una tecnologia cosi' tanto semplice ne' tanto "leggera" dal punto di vista del consumo di risorse.
Un altra via per accedere ai dati e' quella di utilizzare direttamente il DAO, Data Access Obiect. DAO si trova piu' o meno a meta' tra l'ADO e l'OLE DB. Si tratta infatti di un'insieme di oggetti connessi ed API di controllo che consentono l'accesso ai database di tipo Access e ODBC in modo diretto (come ADO), ma senza tutte le complicazioni dell'OLE.
Il diagramma seguente riporta (molto semplificata) la struttura di DAO, almeno per quanto riguarda gli oggetti di interesse piu' comune. Una trattazione completa del DAO e' disponibile sul sito Microsoft e nell'MSDN.
L'oggetto principale DBEngine e' il "motore" del database, il motore fondamentalmente non fa' altro che mantenere i collegamenti tra i vari oggetti "attivi" di DAO, cioe' i Database ed i vari WorkSpace.
DAO consente di avere attivi diversi WorkSpace, in ognuno dei quali possono essere attivi piu' database diversi. Ad ogni WorkSpace possono essere collegate diverse caratteristiche (Utenti, Password, parametri di controllo...).
Notare che gli oggetti Error sono connessi al DBEngine e non alle singole WorkSpace/Database.
DAO e' la soluzione ideale se si vuole accedre tramite C/C++ ad un database di tipo Access o ODBC, senza volere la complicazione delle API di ODBC (DAO usa ODBC automaticamente se e' istruito a farlo), inoltre, data la presenza di una serie di classi MFC di "incapsulamento" di DAO, l'utilizzo mediante le MFC e' notevolmente piu' semplice dell'uso delle OLE DB.
Ora inizia la parte interessante.
L'utilizzo di DAO e' notevolmente semplificato se si utilizzano le corrispondenti classi MFC, tali classi sono identificate dal prefisso CDao.
Per utilizzare le classi DAO occorre includere i file necessari per avere il supporto delle MFC, questo si puo' fare usando:
#include <afx.h> #include <afxdao.h>
Questo e' sufficiente ad includere il supporto DAO e le MFC. Se utilizzate Visual C++, potete ottenere lo stesso risultato usando il Wizard per creare una applicazione che usa le MFC e poi aggiungere AFXDAO.H tra i file di inclusione.
Per utilizzare DAO, per prima cosa occorre "inizializzare" il motore del database, questo si fa' richiamando la funzione AfxDaoInit().
Se la AfxDaoInit non e' richiamata, essa verra' richiamata automaticamente non appena si accede ad una delle classi DAO, quindi strettamente parlando il richiamo non e' obbligatorio, pero' e' buona norma inserirla per chiarificare cio' che il codice si propone di fare (e per evitare problemi il giorno che Microsoft modifica le MFC).
La prima cosa da fare e' quella di creare un'oggetto CDaoDatabase che ci permette di accedere al database che vogliamo gestire.
La creazione del CDaoDatabase puo' essere fatta in due modi: o usando CDaoWorkspace, oppure creando direttamente il CDaoDatabase, in questo secondo caso, un Workspace di default verra' creato automaticamente.
I Database DAO possono essere di tipo Access (normale) oppure fonti dati di ODBC. L'unica differenza consiste nella creazione dell'oggetto Database associato, che nel caso di Access richiede solo il nome (path completo) del file .MDB corrispondente, mentre nel secondo caso richiede la stringa di connessione completa per il database stesso.
DAO consente anche di creare il database da zero, questo si fa' usando l'apposito metodo Create dell'oggetto Database.
Cosa piuttosto strana, creando il database .MDB con DAO si ottiene un database leggermente piu' compatto che usando Access (60Kb contro 72).
Una volta che abbiamo il database abbiamo diverse possibilita' di gestione:
L'oggetto CDaoRecordset messoci a disposizione dalle MFC incapsula tutte le necessarie funzionalita' per accedere ai dati di una o piu' tabelle tramite una query SQL ed eseguire delle manipolazioni sugli stessi dati.
Ricordiamoci che una query (view) e' modificabile solo se e' fatta su non piu' di due tabelle, contiene tutti i campi obbligatori delle due tabelle (o tutti quelli che non hanno un default) e se le tabelle sono piu' di una, solo la tabella "figlia" e' modificabile. Per sintetizzare le possibilita' che una query con piu' di una tabella sia modificabile sono molto basse.
Per creare un Recordset occorrono due cose: un CDaoDatabase attivo ed una query SQL valida.
Dopo di che' usando:
CDaoRecordset recordset = CDaoRecordset( daoDb ); recordset.Open( type, sql, opt );
Il recordset viene aperto.
Il parametro type indica il tipo di recordset da aprire, i tipi supportati sono molteplici:
Il parametro opt indica delle opzioni aggiuntive per il recordset da aprire.
Una volta che abbiamo il recordset aperto ed attivo, possiamo leggerne i dati usando il metodo GetFieldValue(), muoverci tra i vari record usando MoveNext(), MovePrevious(), MoveFirst() e MoveLast().
L'accesso ai dati del recordset e' un po' complicato dal fatto che i dati sono memorizzati sotto forma di COleVariant, una particolare classe di variabili di tipo Variant che permette la memorizzazione di ogni tipo di valore, ma questo ci obbliga a "tradurre" ogni valore usando delle apposite macro-funzioni per poter accedere ai veri dati inseriti.
Le macro funzioni V_ permettono di "tradurre" i valori variant nell'equivalente valore "normale" che puo' essere poi gestito.
Per esempio, supponendo che il campo "x" contenga una stringa, per accedere al valore contenuto occorrera' fare:
CString campo;
COleVariant v;
/* reperisco il campo */
recordset.GetFieldValue( "x", v );
/* converto in stringa */
campo = V_BSTRT( &v );
A questo punto abbiamo il campo in una CString e possiamo gestirlo come piu' ci piace.
Vedere l'MSDN o la guida di Visual C per un'elenco completo delle macro V_ o per i dettagli sull'oggetto COleVariant.
Il sistema piu' semplice per modificare i dati del database e' quello di inviare delle Query di comando al motore del database usando il metodo Execute dell'oggetto CDaoDatabase.
Attenzione: il metodo Execute non puo' essere usato con query che ritornano valori (SELECT).
Una funzione come la seguente:
daoDb.Execute( "DELETE * FROM Tabella;");
Esegue la cancellazione di tutti i record della tabella indicata.
Se la query inviata non e' corretta si verifichera' un'eccezione che dovra' essere recuperata e gestita, altrimenti il programma potrebbe crashare.
Al termine delle operazioni e' buona norma chiudere tutti i Recordset ed il Database richiamando i metodi Close di entrambi, quindi terminare il "motore" di database richiamando la
AfxDaoTerm( );
Questo concludera' le operazioni di gestione ed eliminera' dalla memoria una serie di strutture dati utilizzate in precedenza.
Attenzione: il mancato richiamo della AfxDaoTerm() provoca il crash del programma alla terminazione (qualche schifezza dentro le MFC che non pulisce la memoria come dovrebbe), in un caso ha anche provocato il blocco della macchina con corrispondente reboot forzato.
Il codice di esempio presente consente la gestione di una mini-agenda, questo codice e' sviluppato come Console-Application, quindi niente finestre. La scelta di farlo Console-based ha permesso di concentrarsi sulle funzioni di gestione del database e di ignorare i problemi di gestione dell'interfaccia grafica.
Per verificare il programma occorre Visual C++ versione 4 o superiore, probabilmente il codice e' compilabile anche con Borland, ma non ho provato quindi non sono in grado di dire quali modifiche ci siano da apportare al codice (se ce ne sono).
Per compilare il programma create un nuovo progetto vuoto Win32 console, ed inserite i due sorgenti (DAO.CPP e DAO.H) nel progetto. Quindi dal menu' Project scegliete Propieta', selezionate il progetto e scegliete tra le Generalita' "Usa le MFC".
Compilate ed eseguite.
Il programma gestisce un database Access denominato DAODEMO.MDB, se il database non esiste, viene creato, viene creata una tabella chiamata Anagrafica con alcuni campi.
Le funzionalita' di gestione implementate sono l'elencazione dei record, l'inserimento di un nuovo record e l'eliminazione di un record presente. Non e' stata implementata la modifica di un record esistente.
Create an .MDB File for Microsoft Access Databases - Article ID: Q149558
Using CDaoRecordset::Seek - Article ID: Q149087
Using the DAO SDK dbDao Classes with Visual C++ 4.x - Article ID: Q149392
Using the MFC Database Classes in Console Applications - Article ID: Q152696
I commenti sono aggiunti quando e soprattutto se ho il tempo di guardarli e dopo aver eliminato le cagate, spam, tentativi di phishing et similia. Quindi non trattenete il respiro.
Costantino VENTRUTO Di Costantino VENTRUTO postato il 20/07/2008 14:03
Jack Di Jack postato il 11/12/2008 13:37
Oeps...
Davide Bianchi, lavora come Unix/Linux System Administrator presso una societa' di Hosting in Olanda.
Il presente sito e' frutto del sudore della mia fronte (e delle mie dita), se siete interessati a ripubblicare uno degli articoli, documenti o qualunque altra cosa presente in questo sito per cortesia datemene comunicazione (o all'autore dell'articolo se non sono io), cosi' il giorno che faccio delle aggiunte potro' avvisarvi e magari mandarvi il testo aggiornato.
Questo sito era composto con VIM, ora e' composto con VIM ed il famosissimo CMS FdT.
Questo sito non e' ottimizzato per la visione con nessun browser particolare, ne' richiede l'uso di font particolari o risoluzioni speciali. Siete liberi di vederlo come vi pare e piace, o come disse qualcuno: "Finalmente uno dei POCHI siti che ancora funzionano con IE5 dentro Windows 3.1".