martedì 18 ottobre 2011

From Query To Code

Ecco che cosa succede quando si ha del tempo libero...

Questa è una di quelle cose che generalmente rompe le scatole, dopo aver scritto una 50 di righe di query, c'e' la rottura di trasformarle in codice.

Si quel pallosissimo momento in cui si aggiungono gli apici, si dichiare si scrive e si fa di tutto di più ..

bene con questa classe mi sono risolto anche questo problema, risolto non proprio a me..

public class QueryForLanguage
{ enum language
{
vbnet,
cs,
vb6
}

public string qIN;
public string qOUT;
public language lan;

private void TrasformQuery();
{
qOUT = createQuery(lan);
}

private string createQuery(language lType)
{
return createHeader(lType) + "\r\n" + createBody(lType);
}

private string createBody(language lType)
{
string[] c = qIN.Replace("\n","").Split(new char[]{'\r'});

string output = "";

for (int i = 0; i < c.Length; i++)
{
if (lType == language.cs)
{
output+= "sSqlQuery+=\"" + c[i].Replace("\"","\\\"") + "\";\r\n";
}
else
{
output += "sSqlQuery = sSqlQuery & \"" + c[i].Replace("\"", "\"\"") + "\"\r\n";
}
}

return output;
}

private string createHeader(language lType)
{
if (lType == language.cs)
{
if (txtVariableName.Text.Trim() == "")
{
return "string sSqlQuery =\"\";\r\n ";
}
else
{
return "string "+ txtVariableName.Text.Trim()+ " =\"\";\r\n ";
}
}
else
{
if (txtVariableName.Text.Trim() == "")
{
return "DIM sSqlQuery AS String \r\n sSqlQuery = \"\"";
}
else
{
return "DIM " + txtVariableName.Text.Trim() + " AS String \r\n sSqlQuery = \"\"";
}
}
}
}

venerdì 14 ottobre 2011

How To: Match and Remove Regex

Questa è una cosa che prima o poi mi deciderò di implementare in una classe che eredita string.. perchè giuro torna davvero comoda..


class Program
{
static void Main(string[] args)
{

string x = "DEL_Demo_Test__DEL";

Console.WriteLine(Trim(x, "_DEL"));

Console.ReadLine();
}

private static string Trim(string text, string find)
{
Regex r = new Regex(find+"$");
bool t = r.IsMatch(text);

if (t){ return Regex.Replace(text,find + "$",""); }

return text;
}
}



In questo ( anche se pur breve ) brano di codice è presentato un sistema decisamente comodo per "eliminare un gruppo di caratteri" che terminano una stringa.

L'utilizzo di RegularExpression a volte "salva" da spiacevoli inconvenienti.

Testing Abstract Class

Un amico mi ha chiesto lumi su un comportamento delle classi astratte.

Questo esempio è stato realizzato con lui, al fine unico di poter ottenere il comportamento evidenziato nel main.

Di contro mi è sembrato che questo semplice esempio possa tornare utile anche ad altri e quindi eccolo in pubblicazione...


public abstract class TestAbstract
{
private string _innerText = "Valore Iniziale";

public virtual string Test_A(int a)
{
PrepareInnerText(a);
return _innerText;
}

private void PrepareInnerText(int a)
{
_innerText = (a > 0 ? "Nuovo Valore"+a.ToString()
: "Immesso valore negativo");
}

public virtual string Test_B()
{
return _innerText;
}

}

public class coTest : TestAbstract
{

}


class Program
{
static void Main(string[] args)
{

coTest c = new coTest();

// Valore inziale
Console.WriteLine(c.Test_B());

// Valore positivo
Console.WriteLine(c.Test_A(1));

// valore negativo
Console.WriteLine(c.Test_A(-1));

// valore finale
Console.WriteLine(c.Test_B());

Console.ReadLine();

c = null;

coTest b = new coTest();

// Valore inziale
Console.WriteLine(b.Test_B());

Console.ReadLine();

b = null;
}
}



Si noti che il risultato atteso per Console.WriteLine(b.Test_B()); è "Valore Iniziale"

Un grazie Giovanni !

mercoledì 12 ottobre 2011

How To: Read Tables Definitions C# SqlServer

Sono più che convinto che ci siano parecchi modi per poter fare un analisi di che cosa contiene un Data Base. Ma giusto perchè ce ne sono tanti, ritengo utile condividere il mio.

Il prototipo è decisamente semplice, la logica prevede un accesso ad un DB sql server,
e una scansione di tutto quello che ci può resituire la stored "sp_tables" che è di sistema.
Ottenuto l'elenco delle tabelle, eseguo una scansione nested sulle colonne, in modo da recuperare tutte le altre informazioni ( diciamo quelle che mi servono ), tramite una seconda stored "sp_columns"

Partiamo quindi con la definizione delle tabella.

public class TableDef
{
public string TName { get; set; }
public string FName { get; set; }
public string FType { get; set; }
public string FSize { get; set; }
public string isNLL { get; set; }
}

public class TablesDef: List<TableDef>
{
}


Questo è il mio contenitore...

SqlConnection sc = new SqlConnection();
try
{
sc.ConnectionString = "connection string"

sc.Open();

SqlCommand c = new SqlCommand();
c.Connection = sc;
c.CommandText = "exec sp_tables";
c.CommandType = CommandType.Text;

SqlDataReader reader = c.ExecuteReader();

if (reader.HasRows)
{
while (reader.Read())
{

if (
(reader["Table_Owner"].ToString() != "INFORMATION_SCHEMA")
&&
(reader["Table_Owner"].ToString() != "sys"))
{
tNames.Add(reader["TABLE_NAME"].ToString());
}
}
}
reader.Close();

for (int i = 0; i < tNames.Count; i++)
{
td.AddRange(GetDataForTable(tNames[i], sc));
}
}
catch (Exception ex)
{
/*...*/
}
finally
{
if (sc.State == ConnectionState.Open)
{
sc.Close();
}
sc = null;
}


Questo è il mio processo di estrazione dei nomi delle tabelle, potrebbe essere discutibile la presenza di un DataReader ( ma in questo caso l'ho utilizzato per via della velocità ).

private TablesDef GetDataForTable(string tName, SqlConnection sc)
{

TablesDef td = new TablesDef();

SqlCommand c1 = new SqlCommand();

c1.CommandText = "exec sp_columns @table_name = '" + tName + "'";
c1.Connection = sc;
c1.CommandType = CommandType.Text;


SqlDataAdapter sda = new SqlDataAdapter(c1);

DataTable dt = new DataTable();

sda.Fill(dt);

if (dt!= null)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
TableDef tf = new TableDef();
tf.TName = tName;
tf.FName = dt.Rows[i]["COLUMN_NAME"].ToString();
tf.FType = dt.Rows[i]["TYPE_NAME"].ToString();
tf.FSize = dt.Rows[i]["PRECISION"].ToString();
tf.isNLL = dt.Rows[i]["IS_NULLABLE"].ToString();
td.Add(tf);

}
dt = null;
}

return td;
}


E questa è la modalità con cui estraggo le informazioni relative ai campi.

Al termine del processo ho tutto quello che mi serve in una lista che posso utilizzare per vari scopi.

lunedì 10 ottobre 2011

DataTable to List AsEnumerable

Ancora una volta torno sull'argomento che come sempre rimane aperto a continue evoluzioni.

In questo caso provando con l'IDE2010 e con il framework 4 sfruttando al meglio i delegati ho ottenuto questa nuova versione di quanto già scritto in precedenza.

Quello che ancora non mi convince è come riuscire a implementare un delegato generico, i modo da poter ovviare anche a questo "difetto".

ahi me in questo caso specifico non riesco a generalizzare il delegato e sono stato costretto a implementare due delegati specifici..

public class T1
{
public int Id { get; set; }
public string Value { get; set; }
}

public class TL1: List<T1>
{

}

public class T2
{
public int Id { get; set; }
public string Value { get; set; }
public string Desctiption { get; set;}
}

public class TL2 : List<T2>
{

}



class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable();

dt1.Columns.Add("id");
dt1.Columns.Add("Value");

for (int i = 0; i < 20; i++)
{
dt1.Rows.Add(
i.ToString(),
DateTime.Now.AddDays(i).ToString());
}

DataTable dt2 = new DataTable();

dt2.Columns.Add("id");
dt2.Columns.Add("Value");
dt2.Columns.Add("Description");

for (int i = 0; i < 20; i++)
{
dt1.Rows.Add(
i.ToString(),
DateTime.Now.AddDays(i).ToString(),
"Rows : "+ i.ToString());
}


TL1 l1 = new TL1();
l1.AddRange(
dt1.AsEnumerable().Select(ToListT1)
);

TL2 l2 = new TL2();
l2.AddRange(
dt2.AsEnumerable().Select(ToListT2)
);
}

static T1 ToListT1(DataRow r)
{
return new T1() {
Id = Convert.ToInt32(r["id"]),
Value = r["value"].ToString()
};
}

static T2 ToListT2(DataRow r)
{
return new T2() {
Id = Convert.ToInt32(r["id"]),
Value = r["value"].ToString(),
Desctiption = r["Desription"].ToString()
};
}
}



Tuttavia il risultato è decisamente buono.

venerdì 7 ottobre 2011

How To: Serilize Xml Attribute

Uno dei problemi ricorrenti della serializzazione, è come riuscire a serializzare degli attributi e cosa non da poco, come realizzare degli attributi serilizzabili in una classe.

Il file di Ouput di questo esempio è il seguente

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfEntity
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<entity>
<id isKey="true" isUnique="false">1</id>
<name>11</name>
<description>22</description>
<EntityExtender>
<user>fabio</user>
<creatioDateTime>
2011-10-07T16:27:56.1470345+02:00
</creatioDateTime>
</EntityExtender>
</entity>
<entity>
<id isKey="true" isUnique="false">2</id>
<name>33</name>
<description>44</description>
<EntityExtender>
<user>fabio</user>
<creatioDateTime>
2011-10-07T16:27:56.1470345+02:00
</creatioDateTime>
</EntityExtender>
</entity>
</ArrayOfEntity>



Non è difficile notare che il campo ID presenta due attributi isKey e isUnique.

Per ottenere questo risultato è necessario implementare quanto segue:

public class entityExtender
{
public string user;
public DateTime creatioDateTime;
}

public class entity
{

public class idField
{
[XmlText]
public int idFieldvalue;
[XmlAttribute(AttributeName = "isKey")]
public bool isKey = true;
[XmlAttribute(AttributeName = "isUnique")]
public bool isUnique = false;

}

private string _name;
private string _description;
private entityExtender _entityExtender;

public idField id;


public string name
{
get { return _name; }
set { _name = value; }
}

public string description
{
get { return _description; }
set { _description = value; }
}

public entityExtender EntityExtender
{
get { return _entityExtender; }
set { _entityExtender = value; }
}
}


public class entities : List<entity>
{

}



La parte complessa rimane proprio nella nested che rappresenta il campo id.

public class idField
{
[XmlText]
public int idFieldvalue;
[XmlAttribute(AttributeName = "isKey")]
public bool isKey = true;
[XmlAttribute(AttributeName = "isUnique")]
public bool isUnique = false;

}


In questa classe sono presenti il valore del nodo è idFieldValue e per far ciò è necessario utilizzare l'attributo [XMLText], mentre isKey e isUnique sono [XmlAttribute].

Un xmlText non è diverso dalla rappresentazione di un nodo TEXT ( il banale valore
del nodo testo ).

static void Main(string[] args)
{
element.entities ets = new testSerializer.element.entities();

element.entityExtender ex = new
testSerializer.element.entityExtender()
{
creatioDateTime = DateTime.Now, user = "fabio"
};

element.entity etx1 = new testSerializer.element.entity();
etx1.id = new testSerializer.element.entity.idField()
{ idFieldvalue = 1, isKey = true };
etx1.name = "11";
etx1.description = "22";
etx1.EntityExtender = ex;

ets.Add(etx1);

element.entity etx2 = new testSerializer.element.entity();
etx2.id = new testSerializer.element.entity.idField()
{ idFieldvalue = 2, isKey = true };
etx2.name = "33";
etx2.description = "44";
etx2.EntityExtender = ex;

ets.Add(etx2);

Serializer.XmlHelpers.XmlDeSerializerTool.Serialize<element.entities>http://www.blogger.com/img/blank.gif
(@"demo.xml",ets);
}


Questo è il main che genera l'xml.

Per il serializer vi suggerisco di recuperare il IL MIO !

giovedì 6 ottobre 2011

AppDomain Samples C#

Nell'ottica di comprendere gli effetti di AppDomain su una applicazione ho esteso l'esempio di qualche tempo fa.

In questo nuovo esempio ci servono due soluzione che non sono in referenza fra loro,
se non per la modalità con cui la prima richiama gli altri.

Lo scopo è quindi di creare una console application che richiama un secondo applicativo.

Nel primo caso utilizziamo appDomain e nel secondo caso utilizziamo processInfo.


using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AppDomainTester
{
class Program
{
public static AppDomain currentAppDomain = null;

static void Main(string[] args)
{

Thread t1 = new Thread(GoForIt);

t1.Start();



ProcessStartInfo psi = new
ProcessStartInfo(@"AppDomainTester.External.exe");
Process p = Process.Start(psi);


p.WaitForExit();


Console.ReadLine();
}

public static void GoForIt()
{
currentAppDomain = AppDomain.CreateDomain("c#TestDomain");
currentAppDomain.ExecuteAssembly(@"AppDomainTester.External.exe");

}
}
}


E questo è il codice della console application.

Mentre per l'altra implementata come window form application.

Il form ( banale in tutto e per tutto ) contiene una property Grid in modo da poter
mostrare le differenze fra le due modalità di caricamento.



Ed il sorgente è quindi il seguente.

in program:
static class Program
{
[STAThread]
static void Main()
{

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
}
}


e nella load del form...

public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();

pgMain.SelectedObject = AppDomain.CurrentDomain;
}
}


Quanto emerge appare decisamente interessante.

Il form lanciato con appDoman naturalmente propone in appDomain.current una serei di informazioni molto interessanti.

domenica 2 ottobre 2011

How To: Use Mutex and Thread C#

In più di un occasione mi sono imbattutto nell'annosa situazione di dover riempire una lista con dati che provengono da fonti differenti.

Per risolvere questa situazione ci possono essere davvero molti molti prototipi, tuttavia ogni programmatore ha diritto di scegliere che cosa utilizzare.

Il problema di fondo e che accedere in modo concorrenziale a chi dovrà contenere
i dati potrebbe generalmente essere causa di sovrascritture .. o affini.

In questo esempio utilizzo il Mutex, anche se onestamente ritengo molto più edificante utilizzare il lock.


L'esempio pratico.

public class simpleEntity
{
#region Private Properties
private int _id_simpleEntity = 0;
private string _CreationDate ="";
private string _ThreadOwner ="";
#endregion

#region Public Properties
public int id_simpleEntity
{
get { return _id_simpleEntity; }
set { _id_simpleEntity = value; }
}

public string CreationDate
{
get { return _CreationDate; }
set { _CreationDate = value; }
}

public string ThreadOwner
{
get { return _ThreadOwner; }
set { _ThreadOwner = value; }
}
#endregion
}


La mia "solita entity"..

public class simpleEntityList:List<simpleEntity>
{
Mutex _mtx = new Mutex();

public void AddEntity(simpleEntity se)
{
_mtx.WaitOne();
this.Add(se);
_mtx.ReleaseMutex();
}

public void RemoveEntity(int idx)
{
_mtx.WaitOne();
this.RemoveAt(idx);
_mtx.ReleaseMutex();
}

public int CountEntity()
{
int j = 0;
_mtx.WaitOne();
j = this.Count;
_mtx.ReleaseMutex();
return j;
}
}


Questa è la collection, che tuttavia non è proprio la solita.
Non è difficile notare la presenza del Mutex sugli metodi principali.

public class _threadParameters
{
public int _maxEntity;
public string _owner;
public simpleEntityList _sel;
}


Il mio state object.


public class simpleEntityCreator
{

Mutex _mtx = new Mutex();
public void buildEntity(object lthp)
{
_threadParameters thp = (_threadParameters)lthp;
int startID = Program._sx.CountEntity() +1;

for (int i = 0; i < thp._maxEntity; i++)
{
simpleEntity se = new simpleEntity();
se.id_simpleEntity = startID + i;
se.ThreadOwner = thp._owner;
se.CreationDate = DateTime.Now.ToLongTimeString();
//Program._sx.AddEntity(se);
thp._sel.AddEntity(se);
}

_mtx.WaitOne();
Console.WriteLine("***********************************************");
Console.WriteLine(thp._owner +" ha finito ");
for (int i = 0; i < Program._sx.Count; i++)
{
if (Program._sx[i].ThreadOwner == thp._owner)
Console.WriteLine(" id : " + Program._sx[i].id_simpleEntity.ToString() + "|" +
Program._sx[i].ThreadOwner.ToString() + "|" + Program._sx[i].CreationDate);
}
Console.WriteLine("***********************************************");
_mtx.ReleaseMutex();
}

}


Questa classe si preoccupa di Riempire la lista... e di scrivere che cosa sta
combinando ( come se fosse un Trace... )


class Program
{

public static simpleEntityList _sx = new simpleEntityList();
static void Main(string[] args)
{
Console.WriteLine("Main Start");
Console.ReadLine();


_threadParameters tph1 = new _threadParameters();
_threadParameters tph2 = new _threadParameters();
tph1._sel = _sx;
tph2._sel = _sx;


simpleEntityCreator _sec = new simpleEntityCreator();

Thread tFiller1 = new Thread(
new ParameterizedThreadStart(_sec.buildEntity));
tph1._maxEntity = 20;
tph1._owner = "t1";
tFiller1.Start(tph1);


Thread tFiller2 = new Thread(
new ParameterizedThreadStart(_sec.buildEntity));

tph2._maxEntity = 35;
tph2._owner = "t2";
tFiller2.Start(tph2);

Console.WriteLine("Main End");
Console.ReadLine();
}


}



E questo è il main ....

Per comprendere bene che cosa avvine l'unica è provarlo... anche se in debug, non è sempre comprensibile ( dato che si tratta di due thread distinti ) quale è in azione.