posts - 315, comments - 268, trackbacks - 15

My Links

News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro

Tag Cloud

Article Categories

Archives

Post Categories

Blogs amici

Links

LINQ: ToList e ToArray

Se nella nostra applicazione abbiamo la necessità di leggere molte volte gli stessi dati, può essere conveniente (se questi non cambiano frequentemente nel tempo), l'utilizzo di ToList (o ToArray )  per convertire il risultato di una query linq in un oggetto List o Array da utilizzare come cache dei dati. Supponiamo di avere mappato una tabella Corsi con la seguente entità:

1 [Table(Name="Corso")] 2 public class Corso 3 { 4 5 [Column(IsPrimaryKey=true)] 6 public int cod_Corso; 7 [Column] 8 public string nome_Corso; 9 [Column] 10 public string descrizione_Corso; 11 [Column] 12 public string livello; 13 [Column] 14 public string tipo; 15 [Column] 16 public string categoria; 17 [Column] 18 public bool web; 19 20 [Association(OtherKey = "Fk_Cod_Corso")] 21 public EntitySet<Prenotazione> Prenotazioni; 22 23 }

Se utilizzassimo la query seguente (molto semplice)

1 var query =from c in _corsoTable orderby c.nome_Corso ascending select c;

per estrapolare tutti i corsi contenuti nel database, per visualizzarli, sarebbe sufficiente eseguire un semplice ciclo foreach (il quale richiamerebbe il corrispondente GetEnumerator). Se dovessimo eseguire quesa operazione molte volte durante il ciclo di vita della nostra applicazione, ogni volta che il foreach viene eseguito, viene interrogato il database sottostante,  e questa operazione  comporta ovviamente un certo tempo per essere portata a termine. Sulla mia macchina (portatile con processore Intel T7700  @2.4Ghz con 4GB di Ram e Windows Vista Ultimate), ho provato ad eseguire il seguente codice:

1 2 List<double> tempi = new List<double> (20); 3 4 _corsoTable = db.GetTable<Corso>(); 5 6 IEnumerable<Corso> query = 7 from c in _corsoTable 8 orderby c.nome_Corso ascending 9 select c; 10 11 List <Corso > lstCorso = query.ToList<Corso>(); 12 DateTime startTime; 13 14 for (int i = 0; i < 20; i++) 15 { 16 startTime = DateTime.Now; 17 for (int index = 0; index < 100; index++) 18 { 19 Console.WriteLine("Ciclo {0}---------------------------------------------------------", index); 20 EseguiForEach(lstCorso ); 21 Console.WriteLine("Fine ciclo {0}-----------------------------------------------------", index); 22 } 23 tempi.Add(DateTime.Now.Subtract(startTime).TotalSeconds); 24 } 25 26 Console.WriteLine ("Media:{0}",tempi.Average());

Ripetendo quest'ultimo diverse volte, commentando o meno la riga 11, a secondo se passavo al metodo EseguiForEach, la lista lstCorso o l'oggetto IEnumerable query. Ho ottenuto i seguenti risultati:

# Iterazioni Ciclo esterno #Iterazioni Ciclo Interno Query (media in sec.) lstCorso (media in sec.)
1 10 1,176 0,5590
3 10 0,7601 0,548
5 10 0,7170 0,5770
10 10 0,6714 0,5356
20 10 0,6408 0,5630
1 100 6,527 5,343

Quello che più mi ha sorpreso è il risultato della prima riga. Il tempo medio si riferisce ad un intera esecuzione del ciclo più interno. Penso che per avere dei test più accurati bisognerebbe "azzerare" la memoria prima di ogni esecuzione (magari con un bel riavvio), e prendere in considerazione una tabella composta da un numero maggiore di dati (la tabella presa in esame contiene circa 4000 righe).

In ogni caso è evidente, che quando si ha la necessità di eseguire molte operazioni di lettura sui dati ( e questi non cambiano frequentemente nel tempo) l'utilizzo di una cache di dati può migliorare notevolmente le prestazioni della nostra applicazione.

 

Technorati Tag: ,,

Print | posted on sabato 12 aprile 2008 17:14 | Filed Under [ LINQ ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET