mercoledì 16 novembre 2011

Multi thread ... console application...

Questa volta è colpa mia...

mi sono messo in mente di realizzare un command che mi estragga da una tabella un campo xml, chiaro per quel che mi rigurada la query e statica, ma nulla ci vieta di prendere questa soluzione e di estenderla.

Come sono solito sostenere quello che ho realizzato è sempre una base.. di contro si può fare qualcosa per migliorarlo.

La gigioneria è che per questa situazione è possibile ottenere un thread per ogni stringa di connessione presenete nel app.config, dandomi la possibilità di lavorare su basi dati differenti senza troppe complessità.

Ancora una piccola chicca.. chiamandolo come comando dos.. l'output è già un xml formattato e fruibile...

Che cosa volete di più ?? che legga la query dall'app.config.. ? naaa fatelo voi.


using System;
using System.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace XMLextractor
{
/// <summary>
/// State Object per invocare il thread
/// </summary>
public class stateObject
{
/// <summary>
/// Imposta o restituisce gli elementi da cercare
/// </summary>
public string[] trids;
/// <summary>
/// Imposta o restituisce il percorso
/// </summary>
public string path;
/// <summary>
/// Imposta o restituisce la connessione.
/// </summary>
public string sCnn;
}

class Program
{
/// <summary>
/// Resituisce la query da eseguire
/// </summary>
/// <returns>SELECT *** </returns>
private static string getQuery()
{
//impostare qui la query di ricerca
return "SELECT [campo XML] from Tabella WHERE campo = [CHIAVE]"
}
/// <summary>
/// Restituisce se il file esiste
/// </summary>
/// <param name="fName">Nome del file </param>
/// <returns>True - False</returns>
private static bool fileExist(string fName)
{
return File.Exists(fName);
}

/// <summary>
/// Restituisce se la directory esiste
/// </summary>
/// <param name="dName">Nome della directory</param>
/// <returns>True - False </returns>
private static bool directoryExist(string dName)
{
return Directory.Exists(dName);
}

/// <summary>
/// Scrive il file in base al numero di polizza
/// </summary>
/// <param name="nChiave">Nome del file</param>
/// <param name="path">percorso</param>
/// <param name="fileBody">corpo letto da db</param>
private static void WirteFile(string nChiave,
string path,
string fileBody)
{
TextWriter tw = new StreamWriter(Path.Combine(path, nChiave));
tw.Write(fileBody);
tw.Close();
tw = null;
}

/// <summary>
/// Restituisce l'elenco dei trID letti dal file
/// </summary>
/// <param name="fName">string nome del file</param>
/// <returns>array di file</returns>
private static string[] GetIDs(string fName)
{
string[] dataFile = { };

TextReader tr = new StreamReader(fName);
dataFile = tr.ReadToEnd().Replace("\r", "").Split(new char[] { '\n' });
tr.Close();
tr = null;

return dataFile;

}


/// <summary>
/// Legge da db le chiavi presenti nel file.
/// </summary>
private static void ReadDbData(object obj)
{

stateObject curProcessData = (stateObject)obj;

string[] trID = curProcessData.trids;
string sConn = curProcessData.sCnn;
string dPath = curProcessData.path;


string ext = "<extraction>";
string thrId = Thread.CurrentThread.ManagedThreadId.ToString();
ext += "<thread>" + thrId + "</thread>";
ext += "<connection> " + sConn + "</connection>";

for (int j = 0; j < trID.Length; j++)
{
string sql = getQuery().Replace("[CHIAVE]", trID[j]);

ext += "<node current=\"" + j.ToString() +"\">";
ext += "<trid>" + trID[j]+"</trid>";
ext += "<query>" + sql +"</query>";

using (SqlConnection conn = new SqlConnection(sConn))
{
try
{
conn.Open();
SqlCommand scm = new SqlCommand(sql, conn);
string tdata = (string)scm.ExecuteScalar();

if (tdata != null)
{
WirteFile(trID[j] + ".xml", dPath, tdata);
ext += "<dataSaved>true</dataSaved>";
}
else
ext += "<dataSaved>flase</dataSaved>";

scm = null;
conn.Close();

}
catch (Exception ex)
{

}
finally
{

}
}
ext += "</node>";
}
ext += "</extraction>";
Console.WriteLine(ext);
}

/// <summary>
/// ingresso dell'applicazione.
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
if (args.Contains("h") || args.Contains("H"))
{
Console.WriteLine(
"prototipo chiamata XMLextractor [file id] [outputfolder]");
Console.WriteLine(
"prototipo chiamata XMLextractor [file id] [outputfolder] > xmlDataFile.xml");
Console.ReadLine();
return;
}
string fName = args[0];
string dName = args[1];
Console.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><root>");
if (!directoryExist(dName))
{
Console.WriteLine("<error>Verificare la directory di output</error>");
Console.ReadLine();
return;
}
List<Thread> TRS = new List<Thread>();
if (fileExist(fName))
{
for (int i = 0;
i < System.Configuration.ConfigurationManager.ConnectionStrings.Count;
i++)
{
string sConn = System.Configuration.ConfigurationManager.ConnectionStrings[i].ConnectionString;
ParameterizedThreadStart realThread = new ParameterizedThreadStart(ReadDbData);
Thread tx = new Thread(realThread);
stateObject sO = new stateObject(){
trids = GetIDs(fName),
path=dName,
sCnn = sConn
};
tx.Start(sO);
TRS.Add(tx);
}
}
else
{
Console.WriteLine("<error>il file dei transaction id Non esiste</error>");
}
while (TRS.Count > 0)
{
if (!TRS[0].IsAlive) { TRS.RemoveAt(0); }
}
Console.WriteLine("</root>");
}
}
}


Devo essere onesto l'unica cosa con cui ho litigato forte... è stata la chiusura del tag root...

Nessun commento: