|
Per effettuare un’operazione di ricerca o di filtro tra i record di una DataTable è preferibile ricorrere ad una DataView anziché eseguire una nuova query di selezione o (peggio ancora) un ciclo For…
Facciamo un esempio pratico supponendo di aver caricato in una DataTable la nostra rubrica aziendale e di volerla filtrare per individuare tutti quei record che corrispondono ad un criterio di ricerca impostato, ad esempio in base al Nome ed alla Città.
Potremmo decidere di ripopolare la DataTable utilizzando la seguente query:
SELECT * FROM [Anagrafica] WHERE [Nome] LIKE ‘%cioni%’ AND [Citta] = ‘Firenze’
La soluzione potrebbe essere valida, così facendo però questo tipo di operazione provoca un overhead sulla rete e sul database server provocando traffico e utilizzando risorse che sono molto più lente di quanto possa essere la RAM che ospita i dati già letti nella lista completa, questo tipo di operazione quindi provoca un calo delle prestazioni della nostra applicazione.
Questo calo di performance verrebbe accentuato se il numero dei record presenti nella tabella fosse elevato se pure di dimensioni contenute, (pensiamo ad esempio agli 80.000 record dei C.A.P.) oppure se la richiesta passasse tramite una connessione internet.
Utilizzare una query diretta come questa, non ha alcuna convenienza per le tabelle di tipo anagrafico, ovvero quelle che variano raramente, come la rubrica, la lista CAP, la lista dei comuni, le nazioni eccetera. Ha la sua convenienza al contrario per le tabelle molto grandi, oppure quelle che variano spesso, pensiamo alla lista giacenze del magazzino di un centro commerciale oppure i dati di una linea di produzione o di montaggio.
Appoggiandoci ad una DataView e sfruttando la potenzialità dei dati disconnessi offerti dalla DataTable, potremmo effettuare tutte le ricerche ed i filtri che ci servono con estrema facilità e rapidità leggendo una sola volta la tabella completa nella memoria del PC che utilizza la nostra applicazione.
Come annotazione, calcoliamo che una rubrica con 12000 anagrafiche, con una lunghezza media di 240 caratteri occupano 3MB di ram, e sono davvero molte.
Dopodiché manipoleremo i dati in memoria modificandone la visualizzazione. Una DataView non è altro che una “vista” sui dati che vogliamo visualizzare. E’ come se in una DataGridView rendessimo invisibili quelle righe che non ci servono, nascondendole ma senza eliminarle perché prima o poi ci potrebbero servire...
Facciamo conoscenza con la DataView che troviamo nel Namespace System.Data:
Per crearne una nuova istanza basta dichiararne il costruttore di base.
' VB
Dim dv As New DataView
// C#
DataView mDv = new DataView();
Poi dobbiamo “applicarla” alla DataTable interessata
' VB
' Crea una nuova DataTable.
Dim dt As New DataTable("NomeTabella")
' Applica la DataView.
dv.Table = dt
// C#
DataTable mDt = new DataTable("dtAnagrafica");
mDv.Table = this.mDt;
Ogni DataTable ha una DataView incorporata, la property DefaultView, pertanto è possibile utilizzarla direttamente, oppure possiamo utilizzare uno dei costruttori in overload:
' VB
Dim dv As New DataView(dt)
mDv = new DataView(mDt);
Questo è il costruttore ad un parametro, a cui possiamo indicare qual'è la DataTable a cui applicare la DataView
' VB
Dim dv As New DataView(dt, "Città = 'Firenze'", "Nome", DataViewRowState.Unchanged)
DataView dv = new DataView(dt, "Città = 'Firenze'", "Nome", DataViewRowState.Unchanged);
Questo invece è un costruttore a più parametri con cui creare subito il filtro desiderato.
La proprietà fondamentale dellas DataView è RowFilter, ossia l’espressione che determinerà il filtro sui record.
E’ impostando questa proprietà che riusciremo ad eseguire le operazioni di ricerca, ordinamento e filtro dei nostri dati senza dover ricorrere al database. La proprietà RowFilter è si comporta in modo simile ad una query di selezione ma non può invece effettuare operazioni di aggregazione o di concatenamento perché non è in grado di effettuare una JOIN fra dati provenienti da due DataTable e non è in grado di eseguire raggruppamenti.
In caso sia questa la vostra necessità è necessario popolare direttamente la DataTable con i dati raggruppati oppure agganciati da più tabelle, poi, usando la DataView si potrà effettuare ulteriori operazioni di filtro.
RowFilter è una stringa, viene impostata specificando il nome della colonna da filtrare seguito da un operatore e da un valore. Se il valore è una stringa, così come nell'SQL classico deve essere racchiuso tra due apici 'Valore'.
es. : "Città = 'Firenze'"
Gli operatori sono quelli di base che si utilizzano per le espressioni di confronto nelle DataColumn.Expression e sono: "<, >, <=, =>, <>, =, IN, LIKE, AND, OR, NOT, IS NULL, BETWEEN, +, -, *, /, %". Le informazioni sul loro funzionamento le troviamo qui.
Una volta creata la DataView bisogna ricordarsi di associarla all’origine dati (DataSource) del controllo che vogliamo utilizzare per visualizzare i record filtrati
' VB
' Associa la DataView alla base dati della DataGridView.
Me.DataGridView1.DataSource = dv
' Può essere associata anche alla base dati di una ComboBox.
Me.ComboBox1.DataSource = dv
// C#
// Associa la DataView alla base dati della DataGridView.
this.DataGridView1.DataSource = dv;
// Può essere associata anche alla base dati di una ComboBox.
this.ComboBox1.DataSource = dv;
Tornando alla nostra Anagrafica possiamo sostituire la query a database con questo filtro:
' VB
dv.RowFilter = "Nome LIKE '%cioni%' AND Citta = 'Firenze'"
// C#
dv.RowFilter == "Nome LIKE '%cioni%' AND Citta = 'Firenze'"
Possiamo rendere il filtro dinamico appoggiandoci a dei campi modificabili come ad esempio delle TextBox
' VB
dv.RowFilter = String.Format("Nome LIKE '%{0}%' AND Citta = '{1}'", _
Me.TextBoxNome.Text, Me.TextBoxCitta.Text)
// C#
dv.RowFilter == string.Format("Nome LIKE '%{0}%' AND Citta = '{1}'"
, this.TextBoxNome.Text, this.TextBoxCitta.Text)
Bisogna tener conto che le stringhe dei parametri potrebbero contenere degli apici singoli come nel caso “Nome = 'Dell'Acqua'", in questi casi per evitare una SyntaxErrorException dovuta al troncamento della stringa del valore del filtro, è necessario utilizzare il metodo Replace della classe String
' VB
' Gestisce l'eventuale presenza di uno o più caratteri apostrofo nel valore.
dv.RowFilter = String.Format("Nome = '{0}'", Me.txtCitta.Text.Replace("'", "''"))
// C#
dv.RowFilter == string.Format("Nome = '{0}'", this.txtCitta.Text.Replace("'", "''"))
Possiamo anche applicare un ordinamento ai risultati del filtro impostando la proprietà Sort
' VB
dv.Sort = "Citta"
//C#
dv.Sort = "Citta"
Per l’ordinamento possono essere prese in considerazione una o più colonne
' VB
dv.Sort = "Citta, Nome"
//C#
dv.Sort = "Citta, Nome"
Può essere modificata anche la direzione dell’ordinamento, ossia da crescente a discendente usando le due Keyword SQL ASC o DESC (Ascending Descending).
' VB
dv.Sort = "Citta DESC"
//C#
dv.Sort = "Citta DESC"
E’ possibile inoltre filtrare le DataRow presenti nella DataTable in base al loro stato (RowState) per visualizzare ad esempio solamente le nuove righe aggiunte alla DataTable
' VB
' Filtra tutti i record con Città uguale a Firenze che risultano essere stati
' aggiunti al DataTable.
dv.RowFilter = "Citta = 'Firenze'"
dv.RowStateFilter = DataViewRowState.Added
// C#
// Filtra tutti i record con Città uguale a Firenze che risultano essere stati aggiunti al DataTable.
dv.RowFilter = "Citta = 'Firenze'";
dv.RowStateFilter = DataViewRowState.Added;
Per rimuovere il filtro basta settare a Nothing la proprietà RowFilter
' VB
' Rimuove il filtro.
dv.RowFilter = Nothing
// C#
// Rimuove il filtro.
dv.RowFilter == null
Potreste obiettare che anche la DataTable è in grado di filtrare direttamente i dati tramite il metodo Select generando un’array di DataRow
' VB
Dim foundRows() As DataRow = dt.Select("Città = 'Prato'")
//C#
DataRow[] foundRows = dt.Select("Città = 'Prato'");
E' vero, ma l'Array di DataRow non è un oggetto che possa essere direttamente posto in Binding come DataSource per una DatagridView, pertanto l’uso della DataView è da preferirsi.
Completiamo la panoramica osservando come appoggiandoci al componente BindingSource per gestire la visualizzazione personalizzata dei record, esso ha al suo interno una DataView e ne espone direttamente alcune proprietà e metodi. Pertanto, quanto fin qui descritto è applicabile in modo diretto a questo componente
' VB
' Filtra e ordina i dati tramite il BindingSource.
Me.ElencoFornitori_BindingSource.Filter = "Nome = 'Cioni'"
Me.ElencoFornitori_BindingSource.Sort = "Citta DESC"
// C#
// Filtra e ordina i dati tramite il BindingSource.
this.ElencoFornitori_BindingSource.Filter = "Nome = 'Cioni'";
this.ElencoFornitori_BindingSource.Sort = "Citta DESC";
Conclusioni
In questa breve panoramica abbiamo analizzato solamente le proprietà RowFilter e Sort della DataView apprezzandone l’efficienza e la semplicità d’uso.
Non bisogna però dimenticare che in questo oggetto ci sono altre proprietà, metodi ed eventi molto interessanti che vi consigliamo di andare a scoprire, con l'aiuto di MSDN che abbiamo abbondantemente linkato a questa pagina ove trovate definizioni ed esempi su ogni componente del framework .NET.
Per qualsiasi Feedback, Ulteriore domanda, Chiarimento, oppure se trovate qualche errore usate direttamente il form dei commenti in calce a questo articolo oppure scrivete all'autore .
L'applicazione esempio relativa al codice di questo articolo è disponibile in area risorse.
|