Quando si interroga la fonte dati per ottenere le tabelle, una necessità abbastanza frequente è quella di avere una colonna che sia il risultato di un calcolo di altre, calcolate pero' "al volo" senza dover memorizzare (e quindi mantenere aggiornate) ulteriori colonne nei database.
Cio' si ottiene facilmente con query SQL tipo:
SELECT... , raggio * 3.14 AS circonferenza FROM cerchioppure
SELECT... , pagato-incassato AS differenza FROM pagamenti
SELECT... , "," + colonna + "," AS... (esempio nel caso di stringhe)Inoltre nel caso tipico delle due tabelle clienti e ordini, posso avere la necessita di avere il conteggio degli ordini per quel determinato cliente direttamente come colonna aggiuntiva della tabella clienti, in modo da poterla visualizzare sullo stesso record per avere tutti i vantaggi (ordinamenti confronti etc..).
Anche in questo caso (un po' piu' complesso) si puo' sfruttare la potenza delle query SQL in questo modo:
SELECT nome,count(ordini.id) AS NumOrdini FROM clienti LEFT JOIN ordini ON clienti.nome = ordini.cliente GROUP BY nomedove grazie alla clausola
"GROUP BY" riusciamo a farci dare il numero di record della tabella in join (ordini).
Con ADO.NET riusciamo ad avere questi stessi risultati sfruttando un overload del metodo
Add dell'insieme
Columns (che ci permettere di aggiungere una colonna alla tabella) specificando che questa deve contere i valori risultanti da un'operazione.
Per i primi casi possiamo fare cosi:
miaTabella.Columns.Add("circonferenza", typeof(long), "raggio * 3.14");
Per il caso dei clienti-ordini, sfruttiamo il fatto di avere una relazione nel nostro DataSet tra le due tabelle e ricorriamo alla parola
"Child":
mioDataset.Tables["clienti"].Columns.Add("NumOrdini", typeof(Int16), Count(Child.idOrdine)");
dove con "child" è la tabella ordini che appunto è "figlia" della clienti.
Cosi' troviamo l'informazione che cerchiamo direttamente nella tabella clienti ("padre") del dataset.
Nell'esempio serviva il conteggio (il campo scelto e' casuale dato che nel caso del conteggio ne va bene uno qualsiasi) e la relazione era unica tra le due tabelle, nel caso servisse, (ho piu di una relazione) si deve specificare anche la relazione da usare per effettuare i calcoli:
Count(Child(relazioneClientiOrdini).id)Per questo tipo di colonne, come spiega la guida, le funzioni e le aggregazioni permesse sono:
Convert
Len
Isnull
Iif
Trim
Substring
Sum (somma)
Avg (media)
Min (minimo)
Max (massimo)
Count (conteggio)
StDev (deviazione standard statistica)
Var (varianza statistica)Particolare comodità si trova con le funzioni come
IIf (es: iif(NumOrdini>0,'ok','nessuno')) che permette di "mascherare" i dati (con valori piu utili per la visualizzazione) cosa che con SQL si puo' fare anche direttamente nella query. Ovviamente tutte le colonne calcolate non sono modificabili e quindi sono read-only.
Un paio di casi pratici...Uno dei problemi che ho riscontrato è poter dare come sorgente di dati ad una DropDownList in ASP.NET con piu campi del database. Basta avere una colonna calcolata dove gli si dice che sia la somma (in forma stringa) delle colonne che vogliamo noi, e poi il tipo di separatore, per esempio:
miatabella.Columns.Add("miotesto",typeof(string),"campo1 + ' - ' + campo2 + ' - ' + campo3");
dove i campi possono essere di tipi diverso (data + stringhe + interi) e poi si arrangia ADO.NET a convertire in stringa.
Altro caso in cui ho visto l'ultilita' immediata rispetto alle query direttamente da stringa SQL, è quello nel fare operazioni (come left(..)) sui campi "ntext" in SQL Server (Access ce lo fa fare e ci semplifica un po').
L'esempio pratico in cui mi sono imbattuto era presentare i primi 20 caratteri di un campo descrizione, su pagina web per poter poi dare il link a tutto il dettaglio (tenendo conte del fatto che potrebbe essere anche nullo). Aggiungendo 1a colonna calcolata e bindando l'hyperlink a questo campo i problema e' presto che risolto:
miatabella.Columns.Add("smalldesc",typeof(string),"Iif(Len(testo)>20,SubString(testo,1,20) + '...',testo)");
Eh eh, grazie ADO.NET ;-)
ProPermette di fare operazioni uguali a SQL tra tabelle del DataSet, potenzialmente anche da fonti eterogenee. La parola "child" evita di dover raggruppare per un numero lungo di campi, percio' basta solamente una relazione.
Permette di fare operazioni con tipi di campo che non si possono fare da stringa SQL
ControLa velocita' della versione SQL è sicuramente maggiore perche viene caricato un set di dati gia' calcolati (nel caso di SQL Server poi viene fatto dal motore del server stesso), operazione che viene invece svolta in memoria dal client nel caso di ADO.NET.
Questa lentezza, specialmente con set di dati ridotti, e' mediamente e' quasi impercettibile.