PDA

View Full Version : [C#/MySql]mi serve un guru!


RaouL_BennetH
29-03-2007, 12:23
:(

Son due giorni che sbatto contro un problema :muro:

Allora...

In base a determinate scelte effettuate su un form da parte dell'utente, viene creata una tabella in un database mysql. Questo significa che detta tabella non avrà mai lo stesso numero di colonne e/o lo stesso tipo. Nel caso l'utente faccia la stessa identica scelta, la tabella viene droppata e ricreata. Fin qui, nessun problema, ho gestito il codice che mi fa tutto questo...

Poi, l'utente decide di visualizzare i dati contenuti in questa tabella appena creata, ed anche qui nessun problema, mediante il fantastico oggetto DataGridView, ho gestito il codice necessario a visualizzare i dati su una splendida griglia.

I problemi iniziano adesso....ovvero quando l'utente decide di cambiare qualcosa o di fare un inserimento nuovo all'interno di questa tabella.
Non posso gestire delle query di INSERT o UPDATE perchè a priori non mi è assolutamente noto il numero di campi che conterrà la tabella (ricordando che viene creata a run time in base a delle scelte del momento da parte dell'utente).

Girovagando in rete, ho visto che il connettore di MySql per .NET, fornisce potenti mezzi per ovviare a questo inconveniente. Uno di questi è il MySqlDataAdapter, che ha un metodo Update() strettamente legato con l'utilizzo di un DataGridView e di un DataSet, e un altro è il MySqlCommandBuilder che si preoccupa da solo, una volta legato al data adapter, di creare i comandi necessati di insert, delete e update. Funziona così:


string connessioneDb = "gestisco_la_connessione";
MySqlConnection cn = new MySqlConnection(connessioneDb);
cn.Open();
string selectFromTable = "SELECT * FROM mia_random_tabella";
MySqlDataAdapter adapter = new MySqlDataAdapter(selectFromTable);
DataSet ds = New DataSet();
adapter.Fill(ds, "mia_random_tabella");
//dico alla griglia di prendersi i dati dagli oggetti mysql
griglia.DataSource = ds;
griglia.DataMember = "mia_random_tabella";

//ora, qui dovrei gestire gli eventuali cambi che faccio sulla griglia per restituirli al db

MySqlCommand builder myCommand = New MySqlCommandBuilder(adapter);
adapter.Update(ds, "mia_random_tabella");
//per semplicità nn ho messo il tutto nei vari try_catch_finally



Questo codice, trovato più volte in rete, anche sul sito msdn, non mi funziona affatto :muro:

Ho provato una marea di combinazioni ma senza successo.

Per favore, datemi una mano :ave:

Grazie.

RaouL.

Xalexalex
29-03-2007, 12:32
Sono a digiuno da parecchio di programmazione, però così su due piedi la prima idea che mi verrebbe è salvare in un'altra tabella, righe e colonne di ogni tabella generata dall'utente, e poi comportarsi di conseguenza...

RaouL_BennetH
29-03-2007, 12:44
Sono a digiuno da parecchio di programmazione, però così su due piedi la prima idea che mi verrebbe è salvare in un'altra tabella, righe e colonne di ogni tabella generata dall'utente, e poi comportarsi di conseguenza...

sarebbe impensabile, se l'utente genera dodici tabelle dovrei gestire dodici query per un numero non prevedibile di colonne :(

Xalexalex
29-03-2007, 13:00
sarebbe impensabile, se l'utente genera dodici tabelle dovrei gestire dodici query per un numero non prevedibile di colonne :(

Allora più di così non so aiutarti, mi spiace :D
Buona fortuna comunque :D
Alex

Riordian
29-03-2007, 14:04
Io di solito non uso questo metodo per aggiornare le tabelle ma mi creo delle query utilizzando l'oggetto command,
comunque mi sembra di ricordare che se fai delle modifiche su un dataset poi devi chiamare il metodo AcceptChanges o qualche cosa del genere, altrimenti il dataset rimane nello stato originario.

RaouL_BennetH
29-03-2007, 14:24
Io di solito non uso questo metodo per aggiornare le tabelle ma mi creo delle query utilizzando l'oggetto command,
comunque mi sembra di ricordare che se fai delle modifiche su un dataset poi devi chiamare il metodo AcceptChanges o qualche cosa del genere, altrimenti il dataset rimane nello stato originario.

Eh.. magari potessi utilizzare unq query. Sono impossibilitato perchè non conosco a priori ne il numero di colonne ne il nome delle colonne che formano la tabella, dato che quest'ultima, viene generata a run time dall'utente.

Per il metodo del dataset, l'ho già provato, ma non funziona :( :help:

Riordian
29-03-2007, 14:29
Eh.. magari potessi utilizzare unq query. Sono impossibilitato perchè non conosco a priori ne il numero di colonne ne il nome delle colonne che formano la tabella, dato che quest'ultima, viene generata a run time dall'utente.

Per il metodo del dataset, l'ho già provato, ma non funziona :( :help:

Beh, genera runtime anche la query, il nome delle colonne delle tabelle dovrebbero essere uguali a quelle del db no?

RaouL_BennetH
29-03-2007, 14:41
Beh, genera runtime anche la query, il nome delle colonne delle tabelle dovrebbero essere uguali a quelle del db no?

Si, in effetti è l'unica cosa che credo possibile. Ma.... c'è un piccolo dettaglio, come faccio a farlo a runtime?

Nel senso che la tabella che crea l'utente, potrebbe avere tanto 30 campi, tanto 5, tanto 18. Il nome dei campi lo posso vedere solo attraverso il nome delle colonne del datagridview. Ma scorrere ogni singolo contenuto delle colonne e delle righe del datagridview, per inserirli nella tabella del db, va oltre le mie capacità. Ti sarei grato se potessi farmi un esempio.

Riordian
29-03-2007, 15:07
Si, in effetti è l'unica cosa che credo possibile. Ma.... c'è un piccolo dettaglio, come faccio a farlo a runtime?

Nel senso che la tabella che crea l'utente, potrebbe avere tanto 30 campi, tanto 5, tanto 18. Il nome dei campi lo posso vedere solo attraverso il nome delle colonne del datagridview. Ma scorrere ogni singolo contenuto delle colonne e delle righe del datagridview, per inserirli nella tabella del db, va oltre le mie capacità. Ti sarei grato se potessi farmi un esempio.

Non ho però capito molto bene il problema, cioè tu crei una tabella vuota nel db e poi inizi a riempirla, ok?
La prima volta va tutto bene ed i problemi nascono le volte successive che inserisci nel db,
ma allora per fare tanti rigiri, non conviene dropparsi e ricreare la tabella ogni volta?
Comunque ho idea che queste strade siano abbastanza lente. Comunque dovrebbe essere una cosa del genere

//cominciare una transazione

//cancella tutte le righe dalla tabella

foreach (datarow r in table.Rows)
{
string insert="insert into tabella (";
string values=")VALUES(";
foreach(datacolumn c in table.Columns)
{
insert+=c.ColumnName +",";
values+="'" + r[c.ColumnName] + "',";
}
insert=insert.trimEnd(',') + values.trimEnd(',') + ")";
//esecuzione del comando

}

//chiudi la transazione


tutto messo sotto un bel blocco try catch ovviamente.
Ho però alcuni dubbi:
1) se la mole di dati fosse grande le prestazioni farebbero pena (il dataadapter credo sarebbe più veloce ma non lo ho mai usato)
2) forse le colonne autogenerate potrebbero dare dei problemi

Tieni conto che ci saranno sicuramente degli errori in compilazione.

Riordian
29-03-2007, 15:16
mi è venuto un altro dubbio rispetto al tuo primo post, il dataset, quando modifichi la datagrid viene aggiornato automaticamente? Se non fosse così, il tuo problema potrebbe essere questo.

RaouL_BennetH
29-03-2007, 15:29
mi è venuto un altro dubbio rispetto al tuo primo post, il dataset, quando modifichi la datagrid viene aggiornato automaticamente? Se non fosse così, il tuo problema potrebbe essere questo.

E' appunto questo il problema principale. Se sapessi come "sincronizzare" il dataset con i dati presenti nel datagridview sarei apposto :(

Sul tuo esempio, stavo facendo qualcosa di analogo nell'evento Cell_EndEdit del datagridview, ma le prestazioni sono davvero penose :(


Non ho però capito molto bene il problema, cioè tu crei una tabella vuota nel db e poi inizi a riempirla, ok?
La prima volta va tutto bene ed i problemi nascono le volte successive che inserisci nel db,
ma allora per fare tanti rigiri, non conviene dropparsi e ricreare la tabella ogni volta?


Infatti la tabella viene droppata e ricreata ogni volta, se l'utente crea una tabella con le stesse scelte già effettuate in passato.
La tabella inizialmente non è vuota, ha già dei dati che derivano da delle view su altre tabelle. Perciò l'utente può crearsi la sua tabella personalizzata in base a scelte fatte anche da altri utenti.

RaouL_BennetH
29-03-2007, 15:45
oltretutto, non riesco ad identificare un errore di sintassi che mi viene da:



string update = "UPDATE T";

for(int count = 2; count < lastColumn; count++)
{
update += " SET 'D" + (count - 1 ) + "' = ' " + dataGridView.Rows[e.RowIndex].Cells[count].Value + "' ";
}
update += "WHERE ID_Job = '" + dataGridView.Rows[e.RowIndex].Cells[0].Value + "' ";

......

Riordian
29-03-2007, 15:51
oltretutto, non riesco ad identificare un errore di sintassi che mi viene da:



string update = "UPDATE T";

for(int count = 2; count < lastColumn; count++)
{
update += " SET 'D" + (count - 1 ) + "' = ' " + dataGridView.Rows[e.RowIndex].Cells[count].Value + "' ";
}
update += "WHERE ID_Job = '" + dataGridView.Rows[e.RowIndex].Cells[0].Value + "' ";

comunque hai problemi anche sul sql, il set va furi dal for ;-)

......


sintassi c# o sql? io comunque metterei
update += " SET 'D" + (count -1).ToString() + .......
crei male la stringa sql.



string update = "UPDATE T SET ";

for(int count = 2; count < lastColumn; count++)
{
update += " 'D" + (count - 1 ).ToString() + "' = ' " + dataGridView.Rows[e.RowIndex].Cells[count].Value + "' ,";
}
update = update.TrimEnd(',');
update += " WHERE ID_Job = '" + dataGridView.Rows[e.RowIndex].Cells[0].Value + "' ";



......


sulle prestazioni immaginavo

RaouL_BennetH
29-03-2007, 15:55
sintassi c# o sql? io comunque metterei
update += " SET 'D" + (count -1).ToString() + .......

sulle prestazioni immaginavo


L'errore me lo da sulla sintassi di MySql. Il metodo ToString() l'avevo già messo, e anzi, all'inizio credevo fosse quello, ma anche togliendolo, il risultato non cambia. Mi da sempre:

"You have an error in your SQL Syntax; check the manual that corresponds to your MySqlS server version for the right syntax to use near ''D1 = '6.00' SET 'D2' = '1.00' SET 'D3' = '' " etc...... :muro:

RaouL_BennetH
29-03-2007, 15:59
CHe pirla... in questo caso avevo solo dimenticato 'qualche virgola.... ' :doh:

RaouL_BennetH
29-03-2007, 16:17
Niente :cry:

Quel 'for' non mi viene :help:

RaouL_BennetH
29-03-2007, 16:31
Almeno, il problema del for l'ho risolto. Mettevo erroneamente il valore del nome della colonna della tabella fra singoli apici.

RaouL_BennetH
29-03-2007, 16:59
Al momento riesco a fare quello che mi serve in questo modo:


try
{
using(MySqlConnection cn = ConnClass.Create())
{
string update = "UPDATE " + myRandomTable + " SET ";
for(int count = 2; count < lastColumn; ++count)
{
if(myGrid.Rows[e.RowIndex].Cells[count].Value != null)
{
update += " D"+ (count - 1) " = '" + myGrid.Rows[e.RowIndex].Cells[count].Value + "' ";
update += ",";
}
}
update += "WHERE ID_Job = '" + myGrid.Rows[e.RowIndex].Cells[0].Value + "' ";
MySqlCommand performUpdate = new MySqlCommand(update, cn);
performUpdate.ExecuteNonQuery();
if( cn != null)
{
cn.Close();
cn.Dispose();
}
}
}
catch(MySqlException)
{
Throw
}


Resto in attesa dei vostri preziosi suggerimenti.


RaouL.