Come eseguire query senza utilizzare IDE (C#)

lunedì 11 gennaio 2010 - 17.11

atsap Profilo | Newbie

Salve a tutti! :)
Sono un niubbo in C#, ma un decente programmatore JAVA. Ho un quesito davvero stupido e banale per voi, ma per me abbastanza complesso, considerando che sto ancora cercando di comprendere le meccaniche del c#, affascinante linguaggio.
Allora: io ho un DB creato in SQL Express 2008 e uso come IDE MS Visual C# 2008 Express Ed. Ho due tabelle, una chiamata "utenti" e l'altra chiamata "cellFacts" sulle quali, in seguito, provvederò ad eseguire delle inner join. La cosa che mi interessa, adesso, è questa: ho, nel Main Form, una comboBox che si dovrebbe riempire da DB (in pratica serve per la scelta dell'utente, e vorrei visualizzarne 'nome' e 'cognome'). Se uso l'IDE (spuntando la voce 'Usa elementi associati a dati') posso scegliere AL MASSIMO un valore tra quelli presenti nella tabella 'utenti', e cioè id, nome e cognome, ma solo un valore tra questi. Ora, a me serve che la comboBox sia riempita con NOME e COGNOME, e non con un solo valore tra i due.
In JAVA saprei perfettamente come fare: aprirei una connessione al DB, eseguirei la query (del tipo 'SELECT id, nome, cognome FROM utenti'), storerei il risultato in un array (o un vector...) e poi, con un while (o un for!) riempirei la comboBox e, infine, chiuderei la connessione. Come posso fare tutto questo in C#? Le query create dal generatore di query vanno bene fin quando devo riempire un dataGrid che abbia TUTTI i valori in una tabella... ma a me serve creare delle query "a mano" e che i loro risultati siano accessibili facilmente. Mi aiutate a capire come funziona? Da quanto ho capito esiste un DataSet, che contiene al suo interno TUTTI i valori queraty sul db, e quindi dovrei indirizzare le query direttamente sul DataSet, e se così fosse non ho lontanamente idea di come fare.
Vorrei creare un'architettura del tipo: classe richiedente -> gestore query (che apre e chiude le connessioni e interroga il db con query create a mano da me, non generate dinamicamente dall'IDE -generando risultati inaspettati-), al fine di non "sovraccaricare" la classe richiedente (e anche per questioni di comodità future), come se fosse un design pattern. Esempio in pseudocodice:

classe chiamante() { GestoreQuery gq = new GestoreQuery(); String nomiUtenti = gq.RetrieveNomiUtenti(); } GestoreQuery() { public String[] RetrieveNomiUtenti() { String nomi[]; connectionToDatabase.apri(); query = "SELECT nome FROM utenti"; risultato=eseguiQuery(); while(risultato.finito) { nomi[] = risultato.next(); } } return nomi[]; }

Grazie a tutti :)

tonyexpo Profilo | Senior Member

Ciao

Poi la cosa più semplice è fare una List<string> e passarla al .DataSource della tua combobox aggiungendo i dati come meglio credi (nome + cognome).


Alternativamente puoi passargli un DataTable con la colonna generata (Denominazione), e impostare la proprietà .DisplayMember del combobox sul nome della colonna da utilizzare in output (Denominazione).
usando una select tipo:
SELECT Cognome + ' ' + Nome AS Denominazione FROM Nomi ORDER BY Cognome, Nome


Antonio Esposito
MCTS, MCP

http://blogs.dotnethell.it/espositos

freeteo Profilo | Guru

Ciao atsap,
ti consiglio di usare un codice abbastanza diffuso (che io definisco pattern ormai) per aprirti una connessione,fare la query e farti tornare i dati scelti.
Il codice è questo:
public DataTable GetDati(string sql) { DataTable table = new DataTable(); using (SqlConnection cn = new SqlConnection(...ConnectionString...)) { SqlCommand cmd = cn.CreateCommand(); cmd.CommandText = sql; cn.Open(); IDataReader rd = cmd.ExecuteReader(); table.Load(rd); } return table; }

come vedi, viene usato un "DataTable" (equivalente di rsTable se non ricordo male in Java) che quindi è dinamico sia come righe che come colonne, dipendente dalla stringa sql che vuoi eseguire, quindi direi che è più vicino a quello che ti serve fare (ad esempio se lo dai in pasto alla DataSource di una Gridview vai via tranquillo).


Non ti consiglio però di usare sempre DataTable e DataSet (quest'ultimo è un "macro-raggruppamento" di DataTable [e realzioni]), se hai delle query dove cambia solo la condizione di caricamento (il "where" per intenderci) allora ti conviene poi usare degli oggetti tuoi e raccoglierli in una collection, con un codice di questo tipo:
public static List<Contenuto> GetContenuto() { List<Contenuto> lista = new List<Contenuto>; using (DbConnection conn = DbHelper.GetConnection()) { conn.Open(); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = "SELECT * FROM contenuti"; DbDataReader rd = cmd.ExecuteReader(); while (rd.Read()) lista.Add(BuildContenuto(rd)); } return lista; } private static Contenuto BuildContenuto(DbDataReader rd) { Contenuto c= new Contenuto(); c.Id = Convert.ToInt32(rd["id"]); c.Data = Convert.ToDateTime(rd["data"]); c.Titolo = Convert.ToString(rd["Titolo"]); c.Testo = Convert.ToString(rd["Testo"]); ... return c; }
dove appunto non usi più la DataTable, ma hai un oggetto "contenuto" (nel codice di quel mio progetto si chiamava così, ma poi chiaramente sarà un oggetto tuo) che è tipizzato e ti aiuta molto dato che ti permette di lavorare con le sue proprietà che sono di un tipo ben definito, senza incappare quindi in errori a runtime magari dovuti a conversioni.
Questo è il modo "Domain-Design" ossia definisci le classi (con o senza Linq2Sql o Entity Framework) che compongono il tuo programma, e poi tramite questi metodi vai a leggerli/scriverli sul db...

Ciao.

Matteo Raumer
[MCAD .net, MVP Visual C#]
http://blogs.dotnethell.it/freeteo

atsap Profilo | Newbie

>Ciao atsap,
>ti consiglio di usare un codice abbastanza diffuso (che io definisco
>pattern ormai) per aprirti una connessione,fare la query e farti
>tornare i dati scelti.
>Il codice è questo:
> public DataTable GetDati(string sql)
> {
> DataTable table = new DataTable();
>
>using (SqlConnection cn = new SqlConnection(...ConnectionString...))
> {
> SqlCommand cmd = cn.CreateCommand();
> cmd.CommandText = sql;
> cn.Open();
>
> IDataReader rd = cmd.ExecuteReader();
> table.Load(rd);
> }
>
>
> return table;
> }
>
>come vedi, viene usato un "DataTable" (equivalente di rsTable
>se non ricordo male in Java) che quindi è dinamico sia come righe
>che come colonne, dipendente dalla stringa sql che vuoi eseguire,
>quindi direi che è più vicino a quello che ti serve fare (ad
>esempio se lo dai in pasto alla DataSource di una Gridview vai
>via tranquillo).
>
>
>Non ti consiglio però di usare sempre DataTable e DataSet (quest'ultimo
>è un "macro-raggruppamento" di DataTable [e realzioni]), se hai
>delle query dove cambia solo la condizione di caricamento (il
>"where" per intenderci) allora ti conviene poi usare degli oggetti
>tuoi e raccoglierli in una collection, con un codice di questo
>tipo:
>
> public static List<Contenuto> GetContenuto()
> {
> List<Contenuto> lista = new List<Contenuto>;
>
>using (DbConnection conn = DbHelper.GetConnection())
> {
> conn.Open();
> DbCommand cmd = conn.CreateCommand();
>
> cmd.CommandText = "SELECT * FROM contenuti";
> DbDataReader rd = cmd.ExecuteReader();
>
> while (rd.Read())
> lista.Add(BuildContenuto(rd));
>
> }
>
> return lista;
> }
>
>private static Contenuto BuildContenuto(DbDataReader rd)
> {
> Contenuto c= new Contenuto();
>
> c.Id = Convert.ToInt32(rd["id"]);
> c.Data = Convert.ToDateTime(rd["data"]);
> c.Titolo = Convert.ToString(rd["Titolo"]);
> c.Testo = Convert.ToString(rd["Testo"]);
> ...
> return c;
> }
>
>dove appunto non usi più la DataTable, ma hai un oggetto "contenuto"
>(nel codice di quel mio progetto si chiamava così, ma poi chiaramente
>sarà un oggetto tuo) che è tipizzato e ti aiuta molto dato che
>ti permette di lavorare con le sue proprietà che sono di un tipo
>ben definito, senza incappare quindi in errori a runtime magari
>dovuti a conversioni.
>Questo è il modo "Domain-Design" ossia definisci le classi (con
>o senza Linq2Sql o Entity Framework) che compongono il tuo programma,
>e poi tramite questi metodi vai a leggerli/scriverli sul db...
>
>Ciao.
>
>Matteo Raumer
>[MCAD .net, MVP Visual C#]
>http://blogs.dotnethell.it/freeteo

Sembra una figata! Lo proverò al più presto, ti farò sapere!
L'altra soluzione mi è un po' oscura...

atsap Profilo | Newbie

Mmm... ottengo questo errore:

Si è verificato un errore di rete o specifico dell'istanza mentre si cercava di stabilire una connessione con il server SQL. Il server non è stato trovato o non è accessibile. Verificare che il nome dell'istanza sia corretto e che il server SQL sia configurato in modo da consentire connessioni remote. (provider: Interfacce di rete SQL, error: 26 - Errore nell'individuazione del server/dell'istanza specificata)

e il compilatore "lampeggia" su

cn.Open();

presumo dunque che ci siano problemi di apertura di connessione al DB. Se però faccio fare tutto a lui, tramite IDE, funziona (nel senso che il test di connessione non restituisce problemi)... quale può essere il problema?
Le IDE sono comodissime, è vero, ma quando agiscono così pensantemente... mamma mia...

freeteo Profilo | Guru

Ciao,
gli hai passato la connectionstring?
Se non sai come costruirla guarda qui: http://www.connectionstrings.com

Le cose "IDE" come le chiami tu, io non le uso praticamente mai, se non per sviluppare qualcosa di specifico (ad esempio qualche report) ma tendo sempre a passare per una modellazione mia prima, quindi anche i vari datasource sono quasi sempre riferiti a "oggetti", quindi di fatto "ObjectDataSource"

Ciao.

Matteo Raumer
[MCAD .net, MVP Visual C#]
http://blogs.dotnethell.it/freeteo

atsap Profilo | Newbie

Si, gliel'ho passata: la prendo da qui

Properties.Settings.Default.myConnectionString

che sarebbe questa

Data Source=|DataDirectory|\\nomeDatabase.sdf;

il db non ha password.

E ottengo sempre quell'errore, il n. 26...


atsap Profilo | Newbie

Don't mind... era tutto un errore di forma, stupido: dovevo utilizzare SqlCeConnection, praticamente...
L'ho scoperto per caso, spulciando il file di settings AUTOMATICAMENTE creato dall'IDE... dovrò imparare a controllarla bene.
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5