Dopo una giornata di "duro" ripasso... vediamo alcune delle cose che ho rivisto. Una domanda ma perchè mi sono apparse le scritte con il bianco nel box del codice?
Dettagli sul Command
Vediamo alcuni oggetti della collection Parameters dell'oggetto Command:
- Direction per specificare se il parametro è di input o di output i suoi valori possono essere: Input,Output,InputOutput o ReturnValue
- ParameterName specifica il nome che può essere usato come key per riferirsi al parametro nel codice
- Precision massimo numero di cifre numeric
- Scale massimo numero di decimal
- Size utilizzato con i parametri binari e string per rappresentare la massima dimensione dei dati in una colonna
- SourceColumn se il parametro è legato alla colonna
- SourceVersion quale versione della colonna legata
- Value il valore rappresentato dal parametro
- OleDbType (solo per OleDbParameters)
- SQLType (solo per SQLParameters)
//assegniamo il valore al parametro richiamandolo per il suo indice che è indicato tra []
OleDbCommand1.Parameters[0].Value="Un saluto a tutti i blogger di Ugidotnet";
//assegniamo il valore al parametro richiamando per nome che è indicato tra ()
OleDbCommand1.Parameters("mioParametro").Value="A domani";
Come creiamo il parametro?
/*riprendiamo l'esempio del post di ieri*/
select RagSoc,PIVA from Clienti where (RagSoc=@RagSoc)
/*grazie alla @ abbiamo creato il parametro*/
Per maggiori dettagli rimando come sempre ad msdn
Vediamo ero come assegnare i dati provenienti da un DataReader, vediamo qualche riga di codice
bool Privacy;
int CoRagSoc;
string RagSoc;
/*
recuperiamo il valore conoscendo l'indice di colonna del campo
*/
Privacy=mioDataReader.GetBoolean(5);
/*
qui non sappiamo l'indice di colonna dunque prima lo ritroviamo GetOrdinal
*/
CoRagSoc=mioDataReader.GetOrdinal("RagSoc");
RagSoc=mioDataReader.GetString(CoRagSoc);
Per i result set multipli vedremo di approfondire un giorno o l'altro.
Una cosa carina
Ora parliamo di una cosa carina e divertente(proprio come piacciono a me ) AD Hoc SQL query (questa cosa non mi è nuova...)
E' possibile far eseguire delle query Sql a run-time. Sarebbe consigliabile, qualora si implementasse questa funzionalità, assicurarsi della capacità d'intendere e volere dell'utente . Comunque visto che non tocca al programmatore(ice ) fare questo andiamo avanti. Procediamo in questo modo:
- creare la commad string con le variabili string, usando gli operatori di concatenazione, che rappresentino i valori da inserire a run-time
- aprire la connessione ed eseguire la command
Vediamo con qualche riga di codice quanto detto:
public void Cancel(string laStringa)
{
//creiamo la command string di nome comm
string comm;
// notiamo l'uso del singolo ' se non utilizzato correttamente la query non funziona
comm="DELETE FROM Clienti WHERE RagSoc= ' " + laStringa + " ' ";
OleDbCommand mioComando=new OleDbCommand(comm,laconn);
laconn.Open();
ilComando.ExecuteNonQuery();
laconn.Close();
}
DataAdapter
Il suo compito è di far da ponte tra il database ed il DataSet sfruttando la connessione.
DataSet mioDataSet=new DataSet();
mioDataAdapter.Fill(mioDataSet);
Attenzione!!! Ogni DataAdapter associa 1 ed una sola tabella ossia la DataTable al nostro DataSet, dunque se ci sono più tabelle occorre aggiungere tanti DataAdapter
Possiamo utilizzare DataSet typed oppure untyped, la differenza è nel come possiamo richiamare le varie entità,comunque il DataSet typed richiede uno strong typing per ogni membro. Vediamo con un semplice esempio come si riflette nel codice questa scelta
/*
Supponiamo di voler la Ragione Sociale del primo record nella tabella Clienti appartente al DataSet detto mioDataSet
*/
//DataSet untyped
string RagSoc;
RagSoc=(string)mioDataSet.Tables["Clienti"].Row[0]["RagioneSociale"];
//DataSet typed
string RagSoc;
RagSoc=mioDataSet.Clienti[0].RagioneSociale;
/* NOTA: nel secondo caso il codice è più leggibile */
Ok, abbiamo detto che devono essere strong typing...ma dove dobbiamo mettere le mani?
In pratica la classe in questione è basata su di uno schema file XML (XSD = Xml Schema Definition) che definisce la struttura del DataSet.
NOTA:
Come comprendiamo subito, visto che usiamo la parola schema, se non conosciamo a priori la struttura dei dati con i quali dobbiamo lavorare questa strada non è fattibile.
Supponiamo di conoscere la struttura dei nostri dati dunque dal menù Data scegliamo Generate DataSet e poi....provate un pò.
COME LAVORARE DI CODICE...
Possiamo anche seguire una strada diversa, ossia non utilizzare il DataAdapter vediamo con il box sottostante come fare ( questa modalità mi piace molto di più chissà perchè )
/*
Supponiamo di voler creare un DataSet di nome AziendaF, che utilizzi due tabelle dette Clienti e Fornitori
*/
/* Primo step: creaimo il DataSet vuoto */
DataSet AziendaF=new DataSet();
/*
creiamo ed aggiugiamo al DataSet le due tabelle
*/
DataTable Clienti=new DataTable();
AziendaF.Tables.Add(Clienti);
/**/
DataTable Fornitori=new DataTable();
AziendaF.Tables.Add(Fornitori);
/*
ora supponiamo che abbiamo le seguenti colonne
Clienti: IDCli,RagSocC,PIVAC
Fornitori: IDFo,RagSocF,PIVAF
*/
DataColumn IDCli=new DataColumn("IDClienti");
AziendaF.Tables[0].Column.Add(IDCli);
/**/
DataColumn RagSocC=new DataColumn("RagioneSocile");
AziendaF.Tables[0].Column.Add(RagSocC);
/*PVIAC credo sia ovvio vediamo come passare alla tabella Fornitori*/
DataColumn IDFo=new DataColumn("IDFornitore");
AziendaF.Tables[1].Column.Add(IDFo);
/*......e così via per le altre colonne*/
/*
Lavoriamo adesso sulla riga creando l'oggetto corrispondente
*/
/*lavoriamo sulla tabella Clienti*/
DataRow recordc;
recordc=AziendaF.Tables[0].NewRow();
/*lavoriamo sulla tabella fornitori*/
DataRow recordf;
recordf=AziendaF.Tables[1].NewRow();
/*
ora dopo averle create dobbiamo riempirle, utilizzando una fonte, supponiamo di utilizzare come fonte una ArrayList detta CollString
*/
for (int j=0;j.CollString.Count;i++)
{
recordc[j]=CollString[j];
}
/* ora ricordiamoci che abbiamo popolato il DataRow quindi dobbiamo aggiungero alla Rows Collection del DataTable */
AziendaF.Tables[0].Rows.Add(recordc);
/*
e finalmente abbiamo creato e popolato tutti i membri del nostro DataSet
*/
FLAT FILE
Devo dire che la prima volta che sentii parlare di Flat File e CSV pensai " è una cosa che si mangia?" ed invece neanche questa volta si mangia....uffa....allora i flat file sono i nostri bei file di testo, mentre un CSV (Comma Separeted Values) è un bel file di testo dove il campi sono separati dalla comma (la nostra cara virgola italiana ,).
Per accedere a questi dati e popolare le nostre tabelle la classe che ci viene in aiuto per aprire un flat file è la System.IO.StreamReader,poi per "distinguere" un campo dall'altro utilizziamo la System.String. Senza stare troppo a girarci intorno vediamo un piccolo esempio
/*
Supponiamo che un nostro collega ci ha passato un bel file di testo nominato ClientiItala.txt
del quale non conosciamo il numero di record ma sappiamo che ha 10 campi(colonne) */
/**/
/*Creiamo il nostro DataSet*/
DataSet AziendaF=new DataSet();
/**/
/*creiamo la nostra tabella Clienti ed aggiungiamola alla Table Collection*/
DataTable Clienti=new DataTable("Clienti Italia");
AziendaF.Tables.Add("Clienti Italia");
/*ora dovremmo creare le colonne come fatto nell'esempio precedente
poichè però sono 10 e non m'importa di chiamarle in un modo particolare
usiamo un ciclo di for
*/
DataColumn colonna;
for(int conto=0;conto<10;conto++)
{
colonna=new DataColumn("Colonna "+conto.ToString());
AziendaF.Tables["Clienti Italia"].Columns.Add(colonna);
}
/*
ora creiamo lo StreamReader per leggere il file e la variabile stringa per l'output dello StreamReader
*/
System.IO.StreamReader Leggo=new System.IO.StreamReader(@"C:\ClientiItalia.txt");
string lastringa;
/*
addesso verifichiamo se abbiamo finito di leggere la stringa
*/
while (Leggo.Peek()!=-1)
{
//leggiamo una riga di dati dal file di testo
lastringa=Leggo.ReadLine();
//ora utilizziamo lo split per creare un array
AziendaF.Tables["Clienti Italia"].Rows.Add(lastringa.Split(char.Parse(",")));
}
Relazioni
Abbiamo il nostro oggetto DataRelation dove vengono specificate in una colonna il parent e nell'altra il child.
//creiamo la DataRelation
DataRelation laRelazione=new DataRelation("Relation1",colonna1,colonna2);
//ora aggiungiamola alla Relation collection del nostro DataSet
AziendaF.Relations.Add(laRelazione);
Se vogliamo recuperare le i record con relazioni parent-child utilizziamo:
- GetParentRow che come ci aspettiamo ci ritorna una singola riga
- GetChildRows che ci ritorna un array
DataRow[] Childrecord;
DataRow Parentrecord;
Childrecord=AziendaF.Tables["Clienti Italia"].Rows[3].GetChildRows(ClientiFiliale);
Parentrecord=AziendaF.Tables["Filiale"].Rows[2].GetParentRow(ClientiFiliale);
/* Secondo voi che stiamo facendo ? */
Constraints
Un rapido cenno, nei prossimi giorni approfondiremo...
In italiano potremmo dirle i Vincoli e ne abbiamo di due tipi:
- UniqueConstraint per specificare ch e non ci devono essere duplicati usata tipicamente per la primary key
- ForeignKeyConstraint specifica come devono essere aggiornate le child rows quando la parent row è editata (Cascade o None)
Per creare entrambe è necessario che la proprietà EnforceConstraints sia settata a true (si trova nel DataSet). Ora vediamo qualche dettaglio sulle ForeignKeyConstraint:
- UpdataRule (Cascade opp Null opp SetDefault opp SetNull)
- DeleteRule (Cascade opp Null opp SetDefault opp SetNull)
- AcceptRejectRule (Cascade o Null)
Per il DataBinding etc rimando ai post di Igor
Ed ora test............
powered by IMHO 1.3