lunedì 23 maggio 2011

List T Sort ( )

Quando si utilizzano le liste generiche come dataSource per le dataGrid ci si ritrovi a dover implementare il sort.
Questo avviene perchè nelle list T non è implementato il comparatore di default dato che la list è basata su tipo T generico

public class StringField<E> : IComparer<E>
{
private string FieldName = "";
private SortDirection SortDir = new SortDirection();


public int Compare(E x, E y)
{
int returnValue = 1;
if ((x != null) && (y != null))
{
Type _e = typeof(E);

PropertyInfo _p = _e.GetProperty(FieldName);

string sXvalue = (string)_p.GetValue(x,null);
string sYvalue = (string)_p.GetValue(y, null);

if (SortDir == SortDirection.Ascending)
{
returnValue = sXvalue.CompareTo(sYvalue);
}
else
{
returnValue = sYvalue.CompareTo(sXvalue);
}
}
return returnValue;
}

public StringField(string fName, SortDirection sDirection )
{
FieldName = fName;
SortDir = sDirection;
}
}
Che cosa potevo inventarmi se non un Generco Comparer ?? null'altro. Ahi me avrei voluto provare a creare qualcosa di molto più efficace ma questo probabilmente avrebbe rallentato
il mio processo, nel senso che avrei potuto implicitamente richiedere come parametro il tipo
su cui eseguire il confronto, e quindi tipizzarmi il campo su cui eseguire i confronti.

Bhe ho preferito questa via, in modo da dover implementare dei comparatori specifici
per interi stringhe e date...




martedì 3 maggio 2011

Xls Connector

Ecco un vero e proprio ever green.. Qualcuno tempo fa disse "l'informatica in italia si fa con Excel", se ben ci pensate il più delle volte quest'affermazione è spaventosamente vera.
Se non preoccupante.

Tuttavia è sempre una bella comodità trovarsi un sistema semplice ed efficace per leggere un foglio excel.

Ed ecco che vi presento la mia versione che come sempre è base base, ma torna sempre comoda.

Queste vi servono necessariamente...
using System.Data;
using System.Data.OleDb;


public class XlsConnector
{

public enum ExcelVersion
{
Excel_97,
Excel_2000,
Excel_2010
}

public enum CellValueDirection
{
_input,
_output,
_both
}

public class CellAddres
{
private string _cellAddress;
private CellValueDirection _cellDirection;

public string cellAddress
{
get { return _cellAddress; }
set { _cellAddress = value; }
}

public CellValueDirection cellDirection
{
get { return _cellDirection; }
set { _cellDirection = value; }
}
}

private string _filePath;
private string _fileName;
private ExcelVersion _fileVersion;

private OleDbConnection cnn;

public XlsConnector(string filePath, string fileName, ExcelVersion fileVersion)
{
_fileName = fileName;
_filePath = filePath;
_fileVersion = fileVersion;
}

public bool OpenConnection()
{
try
{
if (
(cnn != null) &&
(cnn.State == ConnectionState.Open)
)
{
cnn.Close();
cnn = null;
}

cnn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
_filePath + _fileName + ";" +
"Extended Properties=" + FileVersionEx(_fileVersion)
);
cnn.Open();

return true;
}
catch
{
return false;
}
}

public DataTable ReadSheet(string SheetName)
{
try
{
DataTable dtx = new DataTable();
OleDbDataAdapter oda = new OleDbDataAdapter(
"SELECT * FROM [" + SheetName + "$]", cnn
);

oda.Fill(dtx);

oda = null;

return dtx;
}
catch
{
return new DataTable("Empty");
}


}

public bool CloseConnection()
{
try
{

if (
(cnn != null) &&
(cnn.State == ConnectionState.Open)
)
{
cnn.Close();
cnn = null;
}

return true;
}
catch
{
return false;
}
}

private string FileVersionEx(ExcelVersion ev)
{
switch (ev)
{
case ExcelVersion.Excel_97: { return "Excel 97"; }
case ExcelVersion.Excel_2000: { return "Excel 8.0"; }
case ExcelVersion.Excel_2010: { return "Excel 10.0"; }
}

return "Excel 97";
}
}

Nel chiamante vi servirà:

xc.OpenConnection(); (per aprire la connessione)

DataTable dtx = xc.ReadSheet("Foglio1"); ( per selezionare il foglio )

xc.CloseConnection(); (per chiudere la connessione)



xc= null;

lunedì 2 maggio 2011

DataTable.Select Vs DataTable.AsEnumerable()

Di recente mi sono posto l'allegra domanda di chi è più performante... Lo so che difficilmente quando Ms realizza qualcosa di nuovo lo passa come peggiore delle precedenti versioni, ma nel
passato qualche pecca l'aveva commessa ( anche se dobbiamo tornare all' RDO ?? ).

In questa prova mi sono messo di buzzo buono per comprendere che cosa combina "Lambda"
quando eseguiamo una selezione.

public class TestDataTableSelect
{
DataTable dt = new DataTable();

public TestDataTableSelect()
{

dt.Columns.Add("field1",typeof(int));
dt.Columns.Add("field2",typeof(string));


for (int i = 0; i < 1000000; i++)
{
dt.Rows.Add(new object[] { i, "A" + i.ToString() });
}
}

public void TestLambda(int selectorLimit)
{


DateTime ttStart = DateTime.Now;
Console.WriteLine(ttStart.ToShortTimeString() + "." +
ttStart.Second.ToString().PadLeft(2, '0') + "." +
ttStart.Millisecond.ToString().PadLeft(3, '0'));

var dr = dt.AsEnumerable().Where(r => (int)r["field1"] < selectorLimit);
DateTime ttEnd = DateTime.Now;

Console.WriteLine("Lambda:" + dr.Count());
Console.WriteLine(ttEnd.ToShortTimeString() + "." +
ttEnd.Second.ToString().PadLeft(2, '0') + "." +
ttEnd.Millisecond.ToString().PadLeft(3, '0'));

TimeSpan ts = ttEnd - ttStart;
Console.WriteLine("Totals:" +
ts.TotalMilliseconds.ToString().PadLeft(3, '0'));
}


public void TestFilter(int selectorLimit)
{

DateTime ttStart = DateTime.Now;
Console.WriteLine(ttStart.ToShortTimeString() + "." +
ttStart.Second.ToString().PadLeft(2, '0') + "." +
ttStart.Millisecond.ToString().PadLeft(3, '0'));

var dr = dt.Select("field1 < "+selectorLimit);
DateTime ttEnd = DateTime.Now;

Console.WriteLine("Normal:"+ dr.Count());
Console.WriteLine(ttEnd.ToShortTimeString() + "." +
ttEnd.Second.ToString().PadLeft(2, '0') + "." +
ttEnd.Millisecond.ToString().PadLeft(3, '0'));

TimeSpan ts = ttEnd - ttStart;
Console.WriteLine("Totals:" +
ts.TotalMilliseconds.ToString().PadLeft(3, '0'));
}
}

Con "stupore" ho notato che in debug, nell'atto della richiesta viene eseguita la
lambda e questo "tacitamente" implica che non solo è più veloce di
Select(string filter) ma i dati dovrebbero essere più vicini all'ultimo aggiornamento.

Questi i dati ottenuti ...

[ora inizio] Prototipo [numero elementi estrtti
[ora fine]
[millisecondi totali]

--------------------------------
09:04.44.034 Lambda:10
09:04.44.047
Totals:13,0008
--------------------------------
09:04.44.299 Normal:10
09:04.46.117
Totals:1818,104
--------------------------------
09:04.46.118 Lambda:100
09:04.46.118
Totals:000
--------------------------------
09:04.46.354 Normal:100
09:04.48.198
Totals:1844,1055
--------------------------------
09:04.48.198 Lambda:1000
09:04.48.198
Totals:000
--------------------------------
09:04.48.436 Normal:1000
09:04.50.273
Totals:1836,105
--------------------------------
09:04.50.276 Lambda:10000
09:04.50.276
Totals:000
--------------------------------
09:04.50.515 Normal:10000
09:04.52.375
Totals:1860,1064
--------------------------------
09:04.52.378 Lambda:100000
09:04.52.379
Totals:001
--------------------------------
09:04.52.627 Normal:100000
09:04.54.454
Totals:1827,1045
--------------------------------

Quanto meno sono omogenei.