Newsgroup: it.comp.software.database
Titolo: Da ODBC ad ADO.NET, un po' di storia (lungo)

Posto qui di seguito una libera traduzione che ho fatto a scopo personale 
(appunti) di alcuni passi che riguardano la storia più recente dell'accesso 
ai dati (da ODBC a 
ADO.NET
), da "
ADO.NET
 2 - Programming with SQL Server 
2005, Oracle and MySQL", di Wallace B. McClure et al., edito da Wiley 
Publishing, Inc. (collana WROX - Professional).
***************
* DATA ACCESS *
***************
All'inizio non c'erano interfacce comuni per accedere ai dati: 
ciascun DataBase Management System (DBMS) esponeva un'API (o 
qualcosa di simile) per consentire l'accesso ai propri dati; 
ciascun sviluppatore doveva avere familiarità con le API del 
"data provider" che stava utilizzando. 
ODBC
====
Open Database Connectivity (ODBC) tentò di dare una soluzione 
al problema di conoscere tutti i dettagli del DBMS utilizzato, 
infatti offriva un'interfaccia comune per accedere a database 
diversi (purchè fosse stato scritto il driver per ODBC, che 
fungeva da wrapper attorno alle API native). Assieme alla 
semplificazione che portava, ODBC presentava però alcuni 
limiti, tra cui la capacità di supportare solo dati relazionali 
(quindi non dati strutturati gerarchicamente - come LDAP) e 
quello di poter manipolare soltanto statement SQL il risultato 
doveva poter essere rappresentabile unicamente in forma di 
righe e di colonne. 
OLE-DB
======
Il passo successivo è stato OLE-DB, ancora largamente usato ai 
nostri giorni, con il quale Microsoft ha migliorato il modello 
di accesso ai dati di ODBC, implementando un'API basata su COM 
(che ha attraversato varie revisioni: all'inizio si appoggiava 
ancora sulle API di ODBC, poi sono stati scritti dei provider 
più efficienti per accedere direttamente ai database, come per 
esempio MS SQL). 
*************
* CONSUMERS *
*************
I linguaggi che supportano i puntatori (per esempio C++ e 
Delphi) potevano interloquire direttamente con le API di ODBC e 
OLE-DB, ma venne comunque introdotto un ulteriore strato, sia 
per gli sviluppatori in linguaggi che non supportano i 
puntatori (per esempio Visual Basic), sia per semplificare 
l'accesso alle API. Questo ulteriore strato è quello dei "Data 
Access Consumers": DAO, RDO, ADO e 
ADO.NET
. 
DAO
===
DAO comparve ai tempi di Visual Basic 2.0 e rappresenta il 
primo tentativo di Microsoft per creare un data consumer. In 
principio si trattò di una cosa piuttosto modesta, che 
supportava soltanto operazioni forward-only su basi dati ODBC; 
però fu l'inizio di una serie di librerie che avrebbero portato 
gli sviluppatori verso il concetto dell'"accesso universale ai 
dati" (UDA, universal data access - la terminologia M$ è 
purtroppo intrisa di questi acronimi). Soprattutto forniva un 
supporto di accesso ai dati via codice, ai linguaggi di "alto 
livello". 
Successivamente a questa prima release senza nome, apparve la 
v1.0, basata sul motore di accesso ai dati JET, il quale venne 
progettato per sfruttare ampiamente "la" desktop database 
application di Microsoft: Access. La DAO 1.0 accedeva ai 
database di Access *senza* passare per ODBC. Poi venne la DAO 
2.0 che supportava anche le connessioni OLE-DB e irrobustiva 
l'accesso (sempre attraverso JET) alle fonti ODBC; quindi 
vennero la 2.5 e la 3.0 che supportavano ODBC 2.0 e i sistemi 
operativi a 32 bit da Win95 in poi. 
Il problema principale di DAO è che è in grado di colloquiare 
soltanto con JET, il quale a sua volta "parla" con i database 
Access (*.MDB) o con ODBC. Tutto ciò si risolve in una sola 
parola: lentezza. 
RDO (e ODBCDirect)
==================
RDO (Remote Data Objects) fu la soluzione ideata da Microsoft 
per sopperire alla scarsa velocità di DAO: per "parlare" con 
database diversi da Access, ora si comunicava direttamente con 
ODBC senza passare attraverso JET. Ciò portò a un incremento 
delle prestazioni, oltre al vantaggio che RDO usava cursori 
client-side (mentre in DAO erano server-side, con un aggravio 
del carico di lavoro per il database server). 
Curiosamente, però, RDO invece di soppiantare DAO, finì per 
coesistergli e questo accadde per diverse ragioni: 
-primo, gli utenti che avevano sviluppato piccole applicazioni, 
 dove le performance non erano un fattore critico, non volevano 
 perdere tempo a riscriverle sulle nuove API; 
-secondo, RDO era stato rilasciato in origine soltanto con VB 
 Enterprise Edition; 
-terzo, con il rilascio di ODBCDirect (un add-on per DAO che 
 inoltrava le richieste a ODBC attraverso RDO invece che 
 attraverso JET), il vantaggio di RDO su DAO si era 
 notevolmente ridotto; 
-infine, non molto tempo dopo Microsoft rilasciò una nuova API 
 per l'accesso universale ai dati: ADO. 
ADO
===
ActiveX Data Objects (ADO) venne introdotta soprattutto con lo 
scopo di fornire un'API di più alto livello (quindi meno 
complessa da manipolare) per interagire con OLE-DB. 
Inizialmente, ADO venne pubblicizzata come il sostituto di DAO 
e RDO. 
Di fatto, ADO introduce delle semplificazioni rispetto a DAO e 
RDO; in RDO, per esempio, per eseguire una semplice query di 
INSERT, lo sviluppatore non può semplicemente creare un oggetto 
rdoQuery ed eseguirlo, ma deve prima creare un oggetto 
rdoEngine, poi un oggetto "figlio" rdoEnvinronment, quindi un 
oggetto rdoConnection e finalmente un rdoQuery. E in DAO la 
situazione è simile. Con ADO invece è più semplice perchè basta 
creare direttamente un oggetto Command, inizializzarlo 
correttamente ed eseguirlo. 
Anche se ADO fu inizialmente rilasciato come complemento di OLE-
DB, il suo scopo non si esaurisce nella comunicazione con le 
origini dati OLE-DB perchè, introducendo il "provider model", 
consente a ciascun produttore di software di scriversi in 
maniera relativamente semplice un "provider dati ADO" per il 
proprio database. 
Con le successive release di ADO vennero introdotte anche 
queste migliorie: 
-aggiornamenti "batch": quando vengono apportate delle 
 modifiche a un recordset residente in memoria, si possono 
 rendere persistenti usando il comando UpdateBatch; 
-accesso ai dati in modalità "disconnessa": capacità di 
 lavorare sui dati anche se non si è connessi continuativamente 
 al database, il che comporta una riduzione del carico di 
 lavoro sul database server; 
-recordset multipli: possibilità di eseguire query che 
 ritornano recordset multipli e possibilità di lavorare su di 
 essi in memoria (MARS - Multiple Active Result Set). 
Tra i lati negativi di ADO si annovera per esempio il fatto che 
lavorare su dati in modalità "disconnessa" è piuttosto 
disagevole, col risultato che molti sviluppatori non usano 
questa possibilità (mentre molti altri non sanno neppure che 
esiste) ed è pratica comune lasciare le connessioni aperte (il 
che si risolve in un maggior carico per il server). Gli 
sviluppatori che invece scelgono di chiudere immediatamente le 
connessioni dopo la lettura dei dati si scontrano con un altro 
problema: il sovraccarico dovuto al fatto che le connessioni 
devono essere continuamente create e distrutte in ciascun 
metodo che compie un accesso ai dati, senza il vantaggio del 
meccanismo di pooling offerto da 
ADO.NET
. 
Come risultato, la maggior parte degli articoli "best practice" 
suggerisce di lasciare aperta una singola connessione e 
utilizzarla in tutti i metodi che fanno uso di accesso ai dati. 
ADO.NET
=======
ADO.NET
 è stato introdotto con .NET Framework e, a differenza 
di quanto l'acronimo ADO potrebbe suggerire, si tratta di 
modello di accesso ai dati interamente riscritto, che nessun 
legame ha con ADO e ActiveX. 
ADO.NET
 supporta la comunicazione alle fonti dati sia 
attraverso ODBC che OLE- DB ma offre anche la possibilità di 
utilizzare dei provider dati più specifici, ottimizzati e più 
performanti (perchè usano del codice specificamente scritto, 
invece che quello generico di ODBC e OLE-DB). Con 
ADO.NET
, 
recordset e cursori sono storia di ieri. 
Il modello è interamente nuovo e consiste di 5 oggetti base: 
1) Connection, che è responsabile di stabilire e mantenere la 
   connessione con la fonte dati, assieme a delle informazioni
   più specifiche, riguardanti la connessione; 
2) Command, che contiene la query che sarà poi inviata
   all'origine dati, assieme a tutti i parametri; 
3) DataReader, che fornisce supporto alla lettura forward-only, 
   per Iterare velocemente attraverso tutti i record; 
4) DataSet, assieme ai suoi oggetti figli rende 
ADO.NET
 
  veramente unico: implementa un meccanismo di memorizzazione 
  per i dati in modalità "disconnessa" - non comunica con 
  alcuna fonte dati ed è completamente disconnesso dalla
  sorgente, i cui dati sono stati utilizzati per popolarlo; 
5) DataAdapter, che funge da ponte tra DataSet e la fonte dati: 
   il suo compito è recuperare i dati dall'oggetto Command e 
   popolare così l'oggetto DataSet; altro suo compito è quello 
   di rendere persistenti (nella fonte dati) i cambiamenti 
   apportati in DataSet. 
Uno dei maggiori passi avanti che sono stati compiuti con 
ADO.NET
 è quello dell'accesso ai dati in modalità veramente 
"disconnessa". Mantenere una connessione a un server come MS 
SQL Server è un'operazione che impiega risorse sul server, così 
è importante limitare il numero le connessioni simultanee. 
Disconnettersi, invece, non appena i dati sono stati estratti, 
rende la connessione libera subito per un altro processo. 
Un altro miglioramento introdotto con 
ADO.NET
 è il connection 
pooling, infatti è dispendioso (in termini di risorse del 
server) non solo mantenere aperta una connessione, ma anche 
crearla e distruggerla. Il pooling delle connessioni risolve 
questo problema perchè quando una connessione viene distrutta -
da codice- il Framework la mantiene aperta nel pool; quando un 
altro processo ha bisogno di una nuova connessione -con le 
stesse credenziali- gli viene fornita quella che si trovava nel 
pool, invece di crearne una nuova. 
ADO.NET
 2.0
===========
ADO.NET
 2.0 ha l'obiettivo di migliorare le prestazioni, pur 
mantenendo la compatibilità all'indietro: tutto il codice 
ADO.NET
 2.0 dovrebbe (?) essere compatibile al 100% con il 
codice 
ADO.NET
 1.0. Alcune aree, come la serializzazione su XML 
e il meccanismo del connection pooling sono state riviste, per 
garantire migliori prestazioni. 
E' stata introdotta la BULK INSERT per aggiungere più righe a 
un database con una singola query. E' stata introdotta la 
capacità di eseguire più query in una sola volta e ricevere una 
serie di risultati (MARS), eliminando tutto il flusso di 
comunicazioni di andata e ritorno che si avevano eseguendo una 
query per volta. Mentre si attendono i dati, possono essere 
eseguite altre operazioni in modalità asincrona. 
Un altro obiettivo è stato quello di ridurre la quantità di 
codice necessaria a svolgere operazioni comuni e ordinarie. 
Altri miglioramenti sono per esempio una nuova API che permette 
di esplorare lo schema di un database. Viene anche offerta la 
possibilità di scrivere codice indipendente dal provider di 
accesso ai dati (per esempio query che non siano più legate 
alla sintassi del database che stiamo utilizzando). 
-- 
Mauro Falzari 
 
  La persona che conosce il vostro segreto
  diventerà il padrone della vostra libertà.
    (François La Rochefoucauld, 1613-1680)

 (quindi non dati strutturati gerarchicamente - come LDAP)
Non so cosa intenda l'autore dicendo "solo" dati relazionali.
Il modello relazionale è il più generico, e può rappresentare
tranquillamente dati gerarchici come anche qualunque altro dato,
avendo però nel contempo superiori qualità di manipolazione e
integrità.
Temo che come al solito si confonda la struttura dei dati con la
loro rappresentazione.
Non dimentichiamoci che il modello relazionale fu inventato
precisamente per risolvere i problemi dei modelli gerarchici e
network.

 integrità.
avevo avvertito che la mia era una traduzione libera..tuttavia ti riporto 
il testo originale:
"ODBC was a huge leap forward and helped to greatly simplify database-
driven application development.
It does have some shortfalls, though. First, it is only capable of 
supporting relational data. 
If you need to access a hierarchical data source such as LDAP, or semi-
structured data, ODBC can’t help you. Second, it can only handle SQL 
statements, and the result must be representable in the form of rows and 
columns."
Ciao.


 riporto il testo originale:
Non occorre, avevo già capito che non era un problema di traduzione:
infatti ho ascritto il mio commento direttamente all'autore e non
a te ;-)
Anzi, colgo l'occasione per ringraziarti per l'utile lavoro svolto.

 a te ;-)
in ogni caso, ho una scarsa conoscenza diretta di ODBC (anche se ho 
lavorato abbastanza con ADO). 
