giovedì 13 marzo 2008

WITH in SQL

Spesso in una query di SQL si ha bisogno di un risultato da utilizzare per varie operazioni.
Anzichè ricalcolare sempre tutto il risultato ogni volta si può utilizzare questa forma:
WITH tempTable(id,name)
as
(
select idUtente, NomeUtente from Utenti
where Affilizazione < @data
)

select * from tempTable.
....
....

Questa funzione è molto potente perchè riduce i tempi di elaborazione dello script.
Da ricordare che WITH deve essere preceduto da GO o dal punto e virgola (';') se prima di WITH c'è un'altra query.

venerdì 30 novembre 2007

Come creare un web control contenitore

Nel nostro controllo modifichiamo la fase di render a run-time inserendo un Javascript che emette l'HTML.

protected override void Render(HtmlTextWriter output){
output.Write("");
}


creiamo la classe per il rendering a design-time.

public class DesignTime : ControlDesigner{

ControlloCon FControllo;

public override void Initialize(System.ComponentModel.IComponent component){
this.FControllo = (ControlloCon)component;
base.Initialize(component);
}

public override string GetDesignTimeHtml() {
try{
if (FControllo.Text == string.Empty)
return GetEmptyDesignTimeHtml();
else
return "
" + FControllo.Text + "
";
}
catch(Exception ex){
return GetErrorDesignTimeHtml(ex);
}
}

protected override string GetEmptyDesignTimeHtml(){
return "
" + typeof(ControlloCon) + " " + FControllo.ID + "
";
}

protected override string GetErrorDesignTimeHtml(Exception e){
return CreatePlaceHolderDesignTimeHtml(e.Message);
}
}

Infine associamo il controllo alla classe di DesignTime.

[Designer("ControlloConDesignTime.DesignTime")]
public class ControlloCon: System.Web.UI.WebControls.WebControl{

martedì 27 novembre 2007

Insert nel dataset di VS2005

Usando i typed dataset di VS2005 come data layer si risparmia un sacco di tempo perchè si auto crea tutto uno strato di classi, metodi e query (per SQL: è questo l'ambiente che uso) che possono essere usati dallo strato business sovrastante.

Oggi ho scoperto una cosa alquanto allarmante, almeno fintanto che non lo si sa.

Mi focalizzo sul metodo di insert di una tabella del dataset. Si può sceglere tra text o stored procedure o table direct.
Nel caso si scelga text si può inserire il testo in due modi:
- usando il query builder (cliccando sugli appositi 3 puntini nel campo CommandText delle proprietà);
- inserendo a mano la query (magari facendo un copia/incolla da SQL manager).

C'è però una notevole differenza tra i due metodi: il primo infatti accoda "di soppiatto" un comando di select conforme con il comando di insert appena editato da noi.
Questo select è FONDAMENTALE in quanto serve per riportare i nuovi valori dal database al dataset che, in caso di assenza del select, rimane con i valori vecchi.
Il caso più eclatante si ha quando l'insert interessa delle righe di una tabella che ha un'indice auto-increment: auto-increment sia sul db (con step positivi) sia sul db (con step negativi)*.
In questo caso gli indici delle righe appena INSERITE sul db manterranno l'indice negativo ma cambieranno stato da added a unchanged. Ad un successivo cambio di stato in Modified si genererà una eccezione di mancanza di chiave primaria in fase di UPDATE, in quanto l'adapter farà affidamento sull'indice di riga rimasto negativo e disallineato dal db.



*: sul perchè è utile fare step negativi nel db per indici auto-increment rimando alla documentazione MS.

venerdì 23 novembre 2007

Problemi a design time (Win.NET)

Scenario:
- si sta sviluppando una interfaccia grafica di un form e si ha bisogno di creare un controllo separato da poi utilizzare nel form principale.
- non si ha l'auto increment nel buid.

Una volta aggiunto lo UserControl nel form, capita di trovarsi questo errore a design time :


per risolverlo basta coronare le proprietà pubbliche dello UserControl con il Custom Attribute
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

e il gioco è fatto.
Da quello che ho capito questo attributo dice al designer di non preoccuparsi di serializzare la proprietà e tirare avanti.
Quello che non mi spiego è perchè ha bisogno di serializzare questa proprietà che non è localizzabile e quindi non è esportata nel file di risorse. Forse è una cosa interna al designer.

sabato 18 agosto 2007

Trovato un server CVS

Dopo aver passato un intero pomeriggio a cercare, installare e testare prodotti free per il backup e il CSV, alla fine mi sono imbattuto in questo CSV server (chiamato CSVNT) scaricabile qui.
Per ora posso dire che è un prodotto all'altezza delle aspettative, mi riservo di tornare sull'argomento più avanti per vedere se dopo un uso più intenso il mio parere sarà cambiato.

Contestualmente vi posso dire che Cobian backup 8 pensandolo come il mio gestore di backup non ha passato la prova in quanto ha ancora dei problemi sull'FTP (pru cambiado utente al servizio, dato che quello di base non può accedere a internet) visto che non chiude mai la sessione; un altro problema è la copia su reti LAN senza dominio: non riesco a dargli il diritto di scrivere sulla directory di destinazione (non escludo che questo sia un problema sistemistico).

mercoledì 15 agosto 2007

Ho scoperto una cosa interessante in Windows.
Tra i settaggi dei Local Security Settings ce ne è uno che recita:
"Network access: Sharing and security model for local accounts".
Se si lascia la selezione: "Classic" si avranno a disposizione per tutte le cartelle la possibilità di definire le autenticazioni in maniera "precisa" (per ogni utente si possono definire le solite autorizzazioni); se si cambia in "Guest only" cambia tutto e l'autorizzazione si semplifica in stile "MS Win Home".

lunedì 6 agosto 2007

Serializzazione di oggetti in C#

Ecco il metodo più semplice per serializzare e deserializzare in un array di byte una istanza di una classe:
public Object Desierializza(Byte[] bytes)
{
System.IO.Stream s = new System.IO.MemoryStream(statistic.DbParameter);
s.Write(bytes, 0, bytes.Length);
BinaryFormatter bf = new BinaryFormatter();
return bf.Deserialize(s);
}

public Byte[] Serializza(Object o)
{
System.IO.Stream s = new System.IO.MemoryStream(statistic.DbParameter);
BinaryFormatter bf = new BinaryFormatter();
return bf.Serialize(s, o);
}