Posts
166
Comments
255
Trackbacks
1
aprile 2008 Entries
Linguaggi di programmazione

A questo link  è presente un confronto a distanza di un anno (Aprile 2007- Aprile 2008) dei linguaggi di programmazione più usati. Qualcuno ha mai utilizzato il linguaggio denominato "D" o "ADA" ?

posted @ martedì 29 aprile 2008 11.00 | Feedback (6)
[OT] Formula 1

Grande Ferrari!!!

Per chi fosse interessato alle  prime tre posizioni:

1° Raikkonen, 2° Massa, 3° Hamilton

Technorati Tag:
posted @ domenica 27 aprile 2008 13.42 | Feedback (7)
Windows Vista SP1

Sono state rilasciate le versioni localizzate del SP1 di Windows Vista.

VISTA SP1 Italiano

posted @ mercoledì 16 aprile 2008 8.03 | Feedback (0)
Report Locali & ReportDataSource

Post nato da una discussione su forum. Supponiamo di avere un DataSet tipizzato contenente un oggetto DataTable "Articoli" come in figura:

DataSet

Supponiamo di avere anche un report locale del tipo:

 Immagine 

Per associare il nostro DataTable al report, possiamo utilizzare un ReportDataSource, scrivendo del codice tipo:

1 Dim dsStampa As New DsStampa() 2 Dim tableArticoli As New DsStampa.ArticoliDataTable() 3 4 'Aggiungo un paio di righe 5 Dim articoloRow As DsStampa.ArticoliRow = tableArticoli.NewArticoliRow() 6 articoloRow.Codice = "CODICE A" 7 articoloRow.Descrizione = " DESCRIZIONE 1" 8 tableArticoli.Rows.Add(articoloRow) 9 10 articoloRow = tableArticoli.NewArticoliRow() 11 articoloRow.Codice = "CODICE B" 12 articoloRow.Descrizione = " DESCRIZIONE 2" 13 tableArticoli.Rows.Add(articoloRow) 14 15 Dim reportDataSource As New Microsoft.Reporting.WinForms.ReportDataSource() 16 17 reportDataSource.Name = "DsStampa_Articoli" 18 reportDataSource.Value = tableArticoli 19 20 Me.ReportViewer1.LocalReport.ReportPath = "Report1.rdlc" 21 Me.ReportViewer1.LocalReport.DataSources.Clear() 22 Me.ReportViewer1.LocalReport.DataSources.Add(reportDataSource) 23 Me.ReportViewer1.RefreshReport()

E' importante non sbagliare ad impostare la stringa della proprietà Name della nostra istanza di reportDataSource con il valore presente nelle proprietà Table del report

Immagine

altrimenti all'interno del ReportViewer verrebbe notificato un errore che indica che non è stata fornita nessuna sorgente dati

Immagine1

Codice sorgente: Test Report.zip

 

Technorati Tag:
posted @ martedì 15 aprile 2008 11.07 | Feedback (2)
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: ,,
posted @ sabato 12 aprile 2008 14.14 | Feedback (0)
MD5

Dopo aver ricevuto suggerimenti in merito al codice del post originale, ho preferito modificare il post precedente senza crearne uno nuovo. Le modifiche sono visibili all'indirizzo http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/04/10/92164.aspx.

posted @ sabato 12 aprile 2008 10.57 | Feedback (0)
MD5 (2)

Dopo aver ricevuto ulteriori suggerimenti (come da commenti) ed aver letto in rete articoli inerenti l'argomento, ho nuovamente modificato la classe MD5Helper, in questo modo:
 

1 public class MD5Helper
2 {
3 System.Security.Cryptography.MD5 _md5 = null;
4
5 public MD5Helper()
6 {
7 _md5 = System.Security.Cryptography.MD5.Create();
8 }
9
10 public byte[] ComputeHash(string text)
11 {
12 return ComputeHash(text, null);
13 }
14
15 private byte[] ComputeHash(string text,byte[] saltBytes)
16 {
17 if (!string.IsNullOrEmpty(text))
18 {
19 if (saltBytes == null) saltBytes = GetSaltBytes();
20 //MD5(text)
21 byte[] textBytes = _md5.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(text));
22 //Crea un unico array di bytes
23 byte[] allBytes = new byte[textBytes.Length+saltBytes.Length];
24
25 Array.Copy(textBytes, 0, allBytes, 0,textBytes.Length);
26 Array.Copy(saltBytes, 0, allBytes, textBytes.Length, saltBytes.Length);
27
28 //MD5((MD5(text)+salt)
29 byte[] hashBytes = _md5.ComputeHash(allBytes);
30 return hashBytes;
31 }
32 else
33 {
34 throw new ArgumentException("Il valore del parametro text non può essere Null o Vuoto");
35 }
36
37 }
38
39 public bool Verify(string text, byte[] hashBytes)
40 {
41 try
42 {
43 byte[] hashSalt = GetSaltBytes();
44 byte[] textHashBytes = ComputeHash(text, hashSalt);
45 string str1 = BitConverter.ToString(textHashBytes);
46 string str2 = BitConverter.ToString(hashBytes);
47 return str1.Equals(str2);
48 }
49 catch
50 {
51 return false;
52 }
53 }
54
55 private byte[] CreateRandomSaltBytes()
56 {
57 byte[] saltBytes = new byte[16];
58 RNGCryptoServiceProvider rng;
59
60 rng = new RNGCryptoServiceProvider();
61 rng.GetBytes(saltBytes);
62
63 return saltBytes;
64 }
65
66 private byte[] GetSaltBytes()
67 {
68 return new byte[] { 13, 100, 12, 15, 13, 55, 33, 55, 44, 33, 84, 67, 190, 254, 89, 99 };
69 }
70
71 public void Close()
72 {
73 _md5.Clear();
74 }
75 }

Ci sono delle piccole osservazioni da fare. Nel caso reale in cui utilizzo questa classe, deve essere "protetta" un unica password (modificabile,senza username, l'applicazione è di tipo Windows Form), per questo ho scelto di utilizzare un salt fisso. Se si dovesse eseguire l'hash di più coppie di username e password, sarebbe necessario creare dei salt random per ogni coppia (usando ad esempio la funzione CreateRandomSaltBytes), memorizzando l'opportuno salt in un database, e utilizzandolo per l'autenticazione degli utenti. Una lettura a riguardo, tratta da MSDN Magazine, la si può trovare al seguente indirizzo: http://msdn2.microsoft.com/it-it/magazine/cc164107(en-us).aspx.  Da quanto appreso in altre letture su internet, RSA Security considera l'MD5 poco sicuro ( correggetemi se sbaglio!), consigliando di utilizzare invece algoritmi di hashing del tipo SHA1, SHA256, SHA384 etc....

Technorati Tag:
posted @ giovedì 10 aprile 2008 14.51 | Feedback (3)
MD5

Causa la necessità di memorizzare dati non in chiaro e di utilizzare l'algoritmo MD5, mi sono creato una piccola classe helper, che a sua volta utilizza la classe System.Security.Cryptography.MD5. Il codice della classe è il seguente:

1 private string _dummyString = "!@HASH#!";
2 System.Security.Cryptography.MD5 _md5 = null;
3 public MD5Helper (){
4 5 _md5 = System.Security.Cryptography.MD5.Create();
6 }
7 8 public byte[] ComputeHash(string text)
9 {
10 if (!string.IsNullOrEmpty(text))
11 {
12 //Concatena il testo da cifrare con una stringa 13 text += _dummyString;
14 //Ritorna l'array di byte 15 byte[] hashedBytes = _md5.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(text));
16 return hashedBytes;
17 }else{
18 throw new ArgumentException("Il valore del parametro text non può essere Null o Vuoto");
19 }
20 }
21 22 public bool Verify(string text, byte[] hashedBytes)
23 {
24 try 25 {
26 if (!string.IsNullOrEmpty(text))
27 {
28 //Computa l'hash 29 byte[] verifyHashedBytes = ComputeHash(text);
30 string str1= BitConverter.ToString(verifyHashedBytes).Replace ("-","");
31 string str2 = BitConverter.ToString(hashedBytes).Replace("-", "");
32 return str1.Equals(str2);
33 }
34 else 35 {
36 throw new ArgumentException("Il valore del parametro textToValidate non può essere Null o Vuoto");
37 }
38 }
39 catch
40 {
41 return false;
42 }
43 }
44 45 public void Close()
46 {
47 _md5.Clear();
48 }

Esempio di utilizzo:

1 MD5Helper md5 = new MD5Helper();
2 hashed = md5.ComputeHash("PIPPO");
3 MessageBox.Show(md5.Verify("PIPPO", hashed).ToString ());

 

Technorati Tag:
posted @ martedì 8 aprile 2008 16.30 | Feedback (2)
[OT] Politiche

Dopo aver visto i vari post, ho provato a cimentarmi con il "giochino". Diciamo che non è proprio quello che mi aspettavo.


e02cc75c

posted @ martedì 8 aprile 2008 14.38 | Feedback (1)
News

View Pietro Libro's profile on LinkedIn

Pietro Libro