Nello scorso post abbiamo creato un TableAdapter e conseguentemente definito uno schema di un DataTable, al quale il TableAdapter è associato.
Abbiamo inoltre fatto vedere l’importanza dei DataTable tipizzati, e la possibilità di poter agire sulle versioni dei dati caricati in locale dal db.
Ora è arrivato il momento di focalizzare la nostra attenzione su di un oggetto che ci permetterà di eseguire operazioni di recupero e inserimento dati sul DB.
Il TableAdapter, infatti, permette a un’applicazione di collegarsi al DB, mettendo cosi le due parti in comunicazione, per essere più precisi il TableAdapter permette di connettersi al DB tramite query e/o stored procedure al fine di riempire un DataTable con i dati ottenuti (query Fill) o di restituire una tabella contenente i dati appena caricati (query GetData).
Un TableAdapter può essere creato nella modalità progettazione guidata in un DataSet tipizzato, alla stessa maniera della creazione di un DataTable. Nonostante ciò il TableAdapter non appartiene allo stesso namespace del DataSet, infatti, se voglio utilizzare un oggetto TableAdapter, non lo richiamerò utilizzando la dicitura:
NomeDataSet.NomeTableAdapter
Ma sarà fatto in questa maniera:
NomeDataSetTableAdapters.NomeTableAdapter
L’esempio che segue fa uso del DB Northwind per il quale è già definito un DataSet e tutti gli oggetti (DataTable e TableAdapter) che lo compongono.
‘VB
Dim northwindDataSet As New NorthwindDataSet()
Dim customersTableAdapter As New NorthwindDataSetTableAdapters.CustomersTableAdapter()
customersTableAdapter.Fill(northwindDataSet.Customers)
NorthwindDataSet northwindDataSet = new NorthwindDataSet();
NorthwindDataSetTableAdapters.CustomersTableAdapter customersTableAdapter =
new NorthwindDataSetTableAdapters.CustomersTableAdapter();
customersTableAdapter.Fill(northwindDataSet.Customers);
Una volta definite le query di Fill e GetData e conclusa la creazione del TableAdapter saranno generate in automatico le query di INSERT, DELETE, UPDATE.
Consiglio - E’ buona norma modificare le query generate in automatico poiché nella clausola WHERE viene fatto un filtro su tutte le colonne della tabella, mentre basterebbe limitare il filtro alla sola chiave, permettendo un accesso al DB per tali operazioni leggermente più rapido.
Il TableAdapter è un componente del framework adatto all’uso dei DataSet fortemente tipizzati, infatti se creiamo un TableAdapter generando una query in modalità guidata, in automatico verrà associato a tale oggetto una DataTable che avrà lo schema definito dalla query da noi scritta in precedenza. A tal proposito c’è da dire che il TableAdapter, purtroppo, ha un limite, infatti, non è possibile (almeno nella modalità guidata) creare query che restituiscano uno schema differente da quello definito dalla query principale (Fill/GetData), ovviamente come in tutte le cose che hanno limitate c’è sempre un modo alternativo per poter superare tali problemi (successivamente vi spiegherò come poter superare questo ostacolo).
All’interno di un DataSet tipizzato, un TableAdapter si presenta graficamente così:

Oltre alle query che restituiscono lo stesso schema della Fill, è possibile creare anche query scalari (restituiscono un valore)
Es.
SELECT Count(*) From MiaTabella
Le query create nel TableAdapter potranno essere richiamate come normali metodi della classe MioTableAdapter
‘VB e C#
MioTableAdapter.MiaQueryFill(MioDataTable, parametro1, …. , parametroN)
Oppure
NuovoDataTable = MioTableAdapter.MiaQueryGetData (parametro1, …. , parametroN)
Il TableAdapter ha anche delle proprietà interessanti, la prima che introduciamo è Connection.ConnectionString, questa è la property in cui va inserita la stringa di connessione al Db, un’altra property è ClearBeforeFill, la quale definisce se un DataTable viene svuotato prima di eseguire una query
Per esempio supponiamo che la proprietà sia settata a TRUE, quando viene richiamato un metodo del TableAdapter, il DataTable associato verrà prima svuotato dei dati che contiene e poi verrà eseguita la query richiesta, viceversa se settata a FALSE i dati caricati con la query richiesta saranno aggiunti a quelli già presenti nel DataTable.
N.B. E’ bene ricordarsi, comunque, di salvare i dati sul DB, se tale operazione si rendesse necessaria, poiché nel caso in cui la proprietà ClearBeforeFill = TRUE, la richiesta di esecuzione di una nuova query comporterebbe la perdita di eventuali modifiche ai dati.
L’altra proprietà da segnalare è GenerateDbDirectMethods, la quale, se settata a TRUE, permette di generare le query di INSERT, DELETE, UPDATE in automatico non appena creata la query di FILL, viceversa, se settata a FALSE, non sarà prevista la generazione automatica di tali metodi, ma, se richiesti, bisognerà crearli successivamente.
Il TableAdapter può essere, inoltre, utilizzato per creare DataTable associativi, infatti, è possibile definire una query di Fill/GetData che metta in join più tabelle, creando così una sorta di vista in locale. A differenza di un TableAdapter che riporta lo schema preciso di una sola tabella del DB, quelli che definiscono un DataTable associativo, non prevedono la generazione automatica delle query di INSERT, UPDATE, DELETE.
Questo tipo di TableAdapter sono veramente utili, ad esempio, nel caso si vogliano mostrare dati in una DataGridView relativa ad una tabella che ha delle chiavi esterne, per non visualizzare in griglia i codici delle chiavi esterne si può mettere in join le tabelle relazionate e far visualizzare la denominazione della riga definita dalla chiave esterna.
Es.

Se volessimo mostrare in una DataGridView le “Question” visualizzeremo del “SurveyTemplate” solo l’id, per risolvere questo problemino è possibile creare nel DataSet il DataTable associativo
Question_SurveyTemplate
Utilizzando la query di Fill/Get Data :
Select Question.id, Question.questinoIndex, Question.questionContent, Question.surveyTemplateID, SurveyTemplate.name As name_surveyTemplate
From Question Inner Join SurveyTemplate
on Question.surveyTemplateID = SurveyTemplate.id

E associare alla proprietà DataSource del DataGridView in questione questo DataTable.
continua --->