INFORMATICA MEDICA
INFORMATICA MEDICA 7. Accesso ai dati Prof. Mauro Giacomini
- Page 2 and 3: Sommario • Proprietà e metodi de
- Page 4 and 5: SqlDataReader: Confronti • Protoc
- Page 6 and 7: DataReader: metodi (1) • Ottiene
- Page 8 and 9: Uso del DataReader: Esempio • Car
- Page 10 and 11: Definizione delle classi: Esempio (
- Page 12 and 13: Caricamento della ListBox • SQL p
- Page 14 and 15: Visualizzazione (1) • Scopo: popo
- Page 16 and 17: Sequenza di esecuzione • Alla loa
- Page 18 and 19: DataTable - DataColumn (1) • Cont
- Page 20 and 21: DataRow • Definizione ed assegnaz
- Page 22 and 23: DataAdapter e DataTable • Il meto
- Page 24 and 25: Popolare un DataSet • Varie possi
- Page 26 and 27: Creazione delle relazioni • Neces
- Page 28: SQLCommandBuilder • Fornisce in m
<strong>INFORMATICA</strong> <strong>MEDICA</strong><br />
7. Accesso ai dati<br />
Prof. Mauro Giacomini
Sommario<br />
• Proprietà e metodi dei seguenti oggetti<br />
• DataReader<br />
• DataAdapter<br />
• DataTable<br />
• DataSet<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataReader: caratteristiche<br />
• Contiene<br />
• solo una struttura dati alla volta (il risultato di un’unica query)<br />
• i valori di un solo record alla volta<br />
• Solo lettura sequenziale<br />
• no ordinamento<br />
• no accesso casuale<br />
• no cambiamento dei valori nei DB<br />
• Lettura solo connessa<br />
• Ottimizzazione elevata<br />
• Tre tipi per i 3 diversi data provider<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
SqlDataReader: Confronti<br />
• Protocollo di comunicazione col server proprio<br />
dei client di SqlServer Tabular Data Stream<br />
(TDS)<br />
• Assenza di provider intermedi<br />
• Metodi di accesso ai dati che restituiscono i<br />
datatype nativi di SQL Server: minimizzazione<br />
delle perdite di precisione<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Creazione del DataReader<br />
• Importazione del namespace<br />
• Dichiarazione<br />
• Item: proprietà che restituisce il valore di una<br />
colonna del record dei dati estratti<br />
• Colonna specificata con il nome (nome del campo della<br />
tabella o alias pubblicato nella query) o la posizione<br />
ordinale nel record (si parte da 0)<br />
• FieldCount: proprietà che restituisce il numero dei<br />
campi del record corrente.<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataReader: metodi (1)<br />
• Ottiene i dati con il metodo ExecuteReader dell’oggetto Command<br />
• DataReader non contiene i dati estratti, ne consente solo la lettura con il<br />
metodo Read<br />
• Si deve sempre invocare il metodo Read all’inizio per generare il<br />
puntatore ai dati<br />
• Se la lettura ha dato esito positivo il valore di Read è true<br />
• Si legge in un loop da cui si esce quando Read restituisce false<br />
• Close: metodo di chiusura della connessione e dell’oggetto DataReader<br />
stesso<br />
• Chiusura automatica gestita dalla proprietà CommandBehaviour<br />
• GetName: restituisce una stringa contenente il nome della colonna<br />
(indicata con la posizione ordinale), serve per le intestazioni delle tabelle<br />
• GetOrdinal: restituisce un numero indicante la posizione della colonna<br />
all’interno del record (indicata con il nome del campo)<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Esempio: commenti<br />
• Estrazione dei dati da visualizzare<br />
• Generazione della stringa SQL<br />
• Uso di procedura esterna<br />
• Lettura in un ciclo While<br />
• Identificazione del primo record<br />
• Scrittura dell’intestazione dei dati stessi con un<br />
ciclo For<br />
• Scrittura del contenuto dei campi stessi con un<br />
altro ciclo for più esterno, usando la proprietà item<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Uso del DataReader: Esempio<br />
• Caricamento di oggetti visuali come ListBox e ComboBox<br />
• Scopo: leggere tutti i record di una tabella e metterne in<br />
nomi nel controllo di tipo lista (vedi routine CaricaListBox)<br />
con il metodo Add della collection Items della lista stessa<br />
• Questa Routine deve essere chiamata dall’evento load della<br />
form<br />
• Gli oggetti di tipo lista possono contenere nella lista degli<br />
items oggetti più complessi del solo nome<br />
• La struttura degli item può essere definita con apposite<br />
classi<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Definizione delle classi<br />
• Selezionare AddClass dal menu progetto, specificandone il<br />
nome<br />
• Vedi listato di definizione delle classi<br />
• Una proprietà per ogni informazione di dettaglio che si vuole<br />
gestire<br />
• Classe Generale per un oggetto numerico con descrizione<br />
alfanumerica, con due proprietà:<br />
• IdOggetto: codice numerico<br />
• NomeOggetto: descrizione dell’oggetto<br />
• Usata per caricare le ComboBox dei fornitori e delle categorie<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Definizione delle classi:<br />
Esempio (VB)<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Definizione delle classi:<br />
Esempio (C#)<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Caricamento della ListBox<br />
• SQL più articolata per valorizzare la classe<br />
• Per ogni record è creato un nuovo oggetto istanziando la<br />
classe, le cui proprietà sono valorizzate leggendo la<br />
proprietà Item dell’oggetto DataReader<br />
• Si aggiunge il prodotto alla lista con il metodo Add della<br />
collezione Items della lista<br />
• Quello che si vede nella lista è determinato dalla funzione<br />
ToString della classe invocata all’atto della valorizzazione<br />
della proprietà, la sua ridefinizione nella classe fa sì che la<br />
proprietà indicata sovrascriva tutte le altre in fase di<br />
visualizzazione<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Caricamento delle ComboBox<br />
• Si usano istanze della classe clsOggettoNum<br />
• Vedi il listato di esempio<br />
• Per ogni record è creato un oggetto della classe le cui<br />
proprietà sono valorizzate con gli item del record stesso<br />
• Si aggiunge l’oggetto agli item della ComboBox<br />
• Anche qui una proprietà sovrascrive le altre in fase di<br />
visualizzazione<br />
• Tutte queste procedure devono essere eseguite durante il<br />
load della form<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Visualizzazione (1)<br />
• Scopo: popolare gli oggetti con i dettagli<br />
dell’Item selezionato<br />
• Nelle TextBox basta l’assegnazione diretta<br />
• Nelle ComboBox va individuato il valore al loro<br />
interno (vedi listato: CercaItemInCombo). Alla<br />
routine si passa l’oggetto in cui cercare (byRef<br />
modificabile) e l’id da cercare (byVal<br />
immodificable)<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Visualizzazione (2)<br />
• Scopo caricare i dettagli nella form<br />
• Vedi listato CaricaFormCollection<br />
• Generazione dell’oggetto di tipo classe indicato con<br />
l’istruzione CType che converte un oggetto che appartiene<br />
alla collezione degli item della lista in un oggetto della classe<br />
indicata.<br />
• Le proprietà di questo oggetto popolano i record o<br />
direttamente o con la subroutine vista prima<br />
• Questa visualizzazione deve essere innescata dall’evento<br />
SelectedIndexChanged della lista dei prodotti<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Sequenza di esecuzione<br />
• Alla load sono chiamate le routine di<br />
caricamento di fornitori, categorie e alla fine dei<br />
prodotti<br />
• Quando sono caricati tutti i prodotti la selezione<br />
automatica del primo prodotto della lista fa<br />
scattare l’evento SelectedIndexChanged così<br />
anche gli altri controlli sono caricati<br />
correttamente<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Modifiche: Aggiornamento<br />
• Creare un nuovo oggetto di tipo classe indicto<br />
• Popolare le proprietà con i nuovi valori digitati negli oggetti<br />
• Eseguire una query di update<br />
• Vedi listato di esempio per la popolazione delle proprietà dell’oggetto classe<br />
indicato<br />
• Di nuovo si usa CType<br />
• Vedi listato di esempio per la scrittura della tabella<br />
• Scrive i parametri della query di update dalle proprietà dell’oggetto classe<br />
indicato<br />
• Chiama la procedura EseguiWriteParametrica<br />
• L’aggiornamento è eseguito alla pressione del tasto aggiorna. Vedi listato:<br />
btnAggiorna_Click<br />
• Dopo l’aggiornamento si deve ricaricare la lista dei prodotti<br />
• Selezionare di nuovo il prodotto modificato per vedere se le modifiche sono state<br />
registrate<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataTable – DataColumn (1)<br />
• Contenitore di memoria strutturato in modo del tutto simile<br />
alla tabella di un DB. Non dipende dal DBMS interfacciato.<br />
• Creazione esplicita con il comando new<br />
• Proprietà TableName: nome univoco<br />
• Definizione dei campi che compongono il record: oggetto<br />
DataColumn<br />
• Columns: Proprietà di tipo collection che contiene i campi fra<br />
i quali coloro che costituiscono la chiave primaria<br />
• Creazione esplicita con il comando new<br />
• Proprietà ColumnName: nome univoco in ogni tabella<br />
• Proprietà DataType: ottenuta con il metodo GetType<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataColumn (2)<br />
• Possibilità di definire dei vincoli con le proprietà<br />
booleane<br />
• Unique<br />
• AllowDBNull<br />
• La tabella ha una collezione di colonne Columns a<br />
cui la colonna definita e completata può essere<br />
aggiunta con il metodo Add<br />
• Possibile definire una lunghezza massima<br />
MaxLength<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataRow<br />
• Definizione ed assegnazione ad una<br />
DataTable per indicarne la struttura<br />
• Accoglie i record da gestire, con la<br />
valorizzazione di tutti i campi<br />
• Quando tutti i campi obbligatori hanno valore<br />
si inserisce la riga nella collezione Rows della<br />
tabella con il comando Add<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataAdapter<br />
• Fornisce più funzionalità rispetto a DataReader<br />
• Indicato per estrarre dati da manipolare<br />
• Dipende dal particolare DBMS<br />
• Creazione con New<br />
• Necessita di:<br />
• Comando Valido<br />
• Connessione attiva<br />
• È possibile sia associare a un DataAdapter il comando e la connessione<br />
in due modi<br />
• Associando dei comandi e delle connessioni precedentemente definite<br />
• Passando all’atto della istanziazione due parametri: la stringa di SQL e la<br />
stringa di connessione, in questo secondo caso la connessione sarà<br />
completamente gestita dal DataAdapter<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataAdapter e DataTable<br />
• Il metodo Fill riempe un DataTable di cui non si deve<br />
neppure definire la struttura<br />
• Tale tabella rimane in memoria, svincolata dalla conessione<br />
e possiamo scorrerla a piacimento evitando le limitazioni che<br />
avevamo con il DataReader.<br />
• Vedi listato: CaricaListBoxDataTable<br />
• Si scorrono tutte le Row del DataTable e per ogni row si<br />
genera un oggetto del tipo classe indicato<br />
• Anche le ComboBox possono essere riempite con<br />
DataAdapter e DataTable, vedi listato: di esempio<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
DataSet<br />
• DataSet: contenitore di oggetti di tipo<br />
DataTable popolate dall’applicazione<br />
• Questa tabelle possono essere correlate tra<br />
loro con apposite relazioni<br />
• Si riproduce un DB nella memoria<br />
• Non dipende dal DBMS<br />
• Dichiarazione semplice e anche semplice<br />
istanziazione<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Popolare un DataSet<br />
• Varie possibilità:<br />
• Definire e costruire in modo esplicito gli oggetti DataTable e<br />
aggiungerli al DataSet, definire le relazioni che li legano e popolarli in<br />
un secondo momento leggendo una fonte di dati (anche non<br />
relazionale)<br />
• Usare il metodo Fill dell’oggetto DataAdapter sia per creare sia per<br />
popolare i DataTable del DataSet<br />
• Una libera combinazione dei due metodi precedenti<br />
• Aggiunta di un DataTable a un DataSet è molto semplice:<br />
DataSet ha una collection (Tables) a cui con il metodo Add<br />
posso aggiungere delle DataTable<br />
• Vedi listato CaricaDataSet<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Commenti<br />
• Tre tabelle nel DB – tre DataTable in un DataSet –<br />
tra stringhe per i tre comandi SQL<br />
• Definizione di un DataSet esplicito<br />
• Un unico DataAdapter da usare per le tre tabelle<br />
• La prima stringa SQL e la stringa di connessione si<br />
passano alla creazione del DataAdapter<br />
• Passando al metodo Fill un DataSet dobbiamo<br />
specificare la Table in cui mettere i dati<br />
• La chiave primaria di ogni tabella viene definita<br />
esplicitamente<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Creazione delle relazioni<br />
• Necessario istanziare un oggetto DataRelation<br />
• Nel comando di creazione è necessario specificare:<br />
• Il nome della relazione<br />
• Gli oggetti DataColumn coinvolti<br />
• Un valore booleano che indica se la relazione è attiva o<br />
no<br />
• Vedi listato: CreaRelazioni<br />
• 4 DataColumn e 2 DataRelation<br />
• Per ogni relazione: una coppia di DataColumn di<br />
due DataTable diverse<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
Scrittura del DB<br />
• Due fasi:<br />
• La scrittura influenza solo i dati locali<br />
• La conferma copia nel DB<br />
• Vedi Listato di esempio<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14
SQLCommandBuilder<br />
• Fornisce in modo automatico le istruzioni SQL necessarie per<br />
trasformare le modifiche su un DataTable in aggiornamenti<br />
effettivi su tabelle del DB.<br />
• Per generare le istruzioni di Insert, Update e Delete l’oggetto<br />
SQLCommandBuilder usa la proprietà SelectCommand per<br />
estrarre un set di dati da confrontare con il DataTable che si<br />
intende aggiorenare<br />
• Da questo confronto l’SQLCommandBuilder crea le istruzioni<br />
SQL che saranno eseguire dall’oggetto dataAdapter.<br />
• Vedi : Conferma aggiornamento<br />
• Annullamento molto semplice: basta invocare il metodo<br />
RejectChanges<br />
Inf. Med. - 7. Accesso ai dati -<br />
A.A. 2013/14