giovedì 7 aprile 2011

From DataTable To List T (entity)

Ho scritto post più recenti che danno maggiori informazioni sull'argomento :
how to: datatable to list
E:
how to: datatable to list solved


E' da un po che ronzo attorno a questo concetto ma non ho mai voluto perderci troppo tempo.http://www.blogger.com/img/blank.gif
Primo perchè per me una classe Entity (e relativa collection / list) è e rimane una classe da popolare tramite conversione da db pura "tramite data reader".
Secondo perchè ho sempre supposto una certa lentezza nell'uso di costrutti Generici applicati
ai dati.

Tuttavia mi sono un filo ricreduto dopo aver fatto questa prova, anche se non mi soddisfa del
tutto Ho ottenuto un buona sostanza un Cast da DataTable a List dove T è una classe
diversa da DataRow.

Certo è vero che il codice scritto è fonte di varie ispirazioni prelevate qua e la dal web, quello
che mi ha sorpreso è la velocità su un numero di elementi inferiore a 100, e la perdita di
presetazioni sopra 100000.

public class MagicTest
{

public class xDemo
{
public int demo0 { get; set; }
public int demo1 { get; set; }
public int demo2 { get; set; }
public string demo3 { get; set; }
public string demo4 { get; set; }
public string demo5 { get; set; }
}

public class Converter<T>
{
public List<T> ToList(DataTable dt)
{
List<T> gr = new List<T>();

Type t = typeof(T);

PropertyInfo[] _p = t.GetProperties();

foreach (DataRow r in dt.Rows)
{
object curIstance = Activator.CreateInstance(t);

foreach (PropertyInfo pr in _p)
{
try
{
object cValue = r[pr.Name];
if (cValue != DBNull.Value)
pr.SetValue(curIstance, cValue, null);
}
catch
{
return null;
}
}

T lOut = (T)curIstance;
gr.Add(lOut);
}

return gr;
}
}

public void doTest()
{

DataTable dtx = new DataTable();

dtx.Columns.Add("demo0", typeof(int));
dtx.Columns.Add("demo1", typeof(int));
dtx.Columns.Add("demo2", typeof(int));
dtx.Columns.Add("demo3", typeof(string));
dtx.Columns.Add("demo4", typeof(string));
dtx.Columns.Add("demo5", typeof(string));

for (int i = 0; i < 1000000; i++)
{
dtx.Rows.Add(new object[] { i, i*2, i*3, "A_"+ i.ToString(),"null","null"});
}

Converter<xDemo> cr = new Converter<xDemo>();


DateTime dsStart = DateTime.Now;
Console.WriteLine("start\t\t:" + dsStart.ToLongTimeString() + "." + dsStart.Millisecond.ToString().PadLeft(3, '0'));
List<xDemo> xD= cr.ToList(dtx);
DateTime dsEnd = DateTime.Now;
Console.WriteLine("end\t\t:" + dsEnd.ToLongTimeString() + "." + dsEnd.Millisecond.ToString().PadLeft(3, '0'));

TimeSpan ts = dsEnd - dsStart;
Console.WriteLine("total\t\t:" + ts.TotalMilliseconds.ToString());

}

}


E questi sono i miei risultati :

Case :10
start :12.24.34.459
end :12.24.34.484
total :24,9033

Case :100
start :12.27.56.234
end :12.27.56.258
total :23,9267

Case :1000
start :12.30.16.135
end :12.30.16.172
total :36,6225

Case :10000
start :12.33.53.492
end :12.33.53.649
total :156,256

Case :100000
start :12.34.32.124
end :12.34.33.572
total :1447,8095

Case :1000000
start :12.37.32.798
end :12.37.46.708
total :13910,2021


Soprattutto questi ultimi due ... mi fanno un po rilflettere.. ma su cifre comprese fra i 10000
e 50000 elementi la risposta non è male. Sarebbe carino testarlo su un db, o se qualcuno potesse
fare qualche test per me su macchine con prestazioni diverse...


Nessun commento: