Da Dataset a tabella database

venerdì 13 febbraio 2009 - 10.45

Luigi3 Profilo | Junior Member

Ciao a tutti,
sono incappato in questo dubbio: esiste un modo "automatico" per passare tutti i dati contenuti in un dataset direttamente in una tabella di un database? L'esatto contrario è semplice basta fare un .fill

Oppure devo scorrermi tutto il dataset e fare una insert per ogni riga?

grazie

totti240282 Profilo | Guru

Devi usare un dataadapter e fare un dataadapter.update(dataset)
C'è solo un capitano !!!!!!

Luigi3 Profilo | Junior Member

Ho due problemi:
1) ho messo i miei dati in un dataTable, analizzo riga x riga tutto questo datatable e se è vera una condizione volgio modificare alcune colonne di questo datatable, come faccio?
Ho provato con : dataTable_A.Rows[j].ItemArray[0]="1";
ma se vado a rileggere la riga, la colonna 0 è ancora null.

2) dataAdapterA.Update(dataTable_A);
Non funziona. Praticamente io elaboro un dataTable nel codice e poi vorrei copiarla in una tabella (access). Manca qualcosa? Forse il commandupdate di quel dataadapter? Come lo costruisco?

Jeremy Profilo | Guru

Ciao Luigi,
Puoi mostrare un pò più di codice relativo al popolamento del dataset???
Da quello che dici, si capisce che usi già, una dataadapter per popolare il dataset.
Quindi, è sufficiente modificare i dati della Datatable presente nel Dataset, successivamente eseguire l'Update del dataAdapter.

Per modificare il valore di una campo della DataTable puoi fare così:

TuoDataSet.dataTable_A.Rows[j].Item[0]="1";

Attento che la colonna con indice 0 non sia un campo di tipo contatore.

Facci sapere...
Ciao

Luigi3 Profilo | Junior Member

Grazie 1000 per la collaborazione, spero sia chiaro quello che scrivo.

Tralasciando la connectionstring che cmq è esatta, il mio obiettivo è: leggere una tabella Access, copiarla in un dataTable, aggiungere delle colonne, popolarle e rispostare il tutto su un'altra tabella access. Il codice è in c#.

//dichiaro le strutture
DataSet dS = new DataSet();
DataTable dataTable_Err, dataTable_Roll, dataTable_RollExt = null;

//dichiaro le query per popolare i datatable
string queryStringErr = "SELECT * FROM Errors";
string queryStringRoll = "SELECT * FROM Roll";

OleDbCommand dbCommandErr = new OleDbCommand(queryStringErr, oleConn);
OleDbCommand dbCommandRoll = new OleDbCommand(queryStringRoll, oleConn);

OleDbDataAdapter dataAdapterErr = new OleDbDataAdapter(dbCommandErr);
OleDbDataAdapter dataAdapterRoll = new OleDbDataAdapter(dbCommandRoll);
OleDbDataAdapter dataAdapterRollExt = new OleDbDataAdapter(dbCommandRollExt);

dataTable_Err = new DataTable();
dataTable_Roll = new DataTable();
dataTable_RollExt = new DataTable();

//riempio i datatable
dataAdapterErr.Fill(dataTable_Err);
dataAdapterRoll.Fill(dataTable_Roll);

//aggiungo 3 colonne al datatable RollExt
DataColumn dcMod = new DataColumn("Modified", System.Type.GetType("System.String"));
DataColumn dcAdd = new DataColumn("Added", System.Type.GetType("System.String"));
DataColumn dcAssPlnt = new DataColumn("Area", System.Type.GetType("System.String"));

dataTable_RollExt.Columns.Add(dcMod);
dataTable_RollExt.Columns.Add(dcAdd);
dataTable_RollExt.Columns.Add(dcAssPlnt);

//riempio il datatable RollExt con i dati del datatable Roll
dataAdapterRoll.Fill(dataTable_RollExt);

Fin qui tutto OK

Faccio le mie variazioni al datatable RollExt -> qui non mi funziona la modifica dei campi..... dataTable_RollExt.Rows[j].ItemArray[0]="1";
solo .Item[] non esiste

Successivamente vorrei riversare il datatable Roll_ext nella tabella Access

Ho provato con:
dataAdapterRollExt.Update(dataTable_RollExt);

Ma non va.

Jeremy Profilo | Guru

>Tralasciando la connectionstring che cmq è esatta, il mio obiettivo
>è: leggere una tabella Access, copiarla in un dataTable, aggiungere
>delle colonne, popolarle e rispostare il tutto su un'altra tabella
>access. Il codice è in c#.

Il problema, a mio avviso, rimane nel fatto che tu modifichi la struttura della DataTable.
L'update del dataadapter lo puoi fare per aggiornare i dati della stessa tabella del quale ha precedentemente eseguito un Fill.
La struttura della DataTable, deve essere identica a quella della tabella nel DB.

Comunque, per fare una prova, prova a modificare semplicemente i valori nella datatable,senza aggiungere le colonne, e prova a vedere se in questo caso ti esegue correttamente l'update.

Facci sapere....
Ciao

Luigi3 Profilo | Junior Member

Comunque anche la tabella access dove andro' a copiare i dati presenta quelle stesse colonne aggiunte.

Vorrei provare a modificare qualche dato del datatable ma non ci riesco...
Come dicevo quando faccio la: dataTable_RollExt.Rows[j].ItemArray[0]="1"
se ricontrollo in debug lo stesso valore, vedo che è ancora al valore precedente, ovvero Null.


Ma una domanda: quando faccio la fill, devo in precedenza impostare la query di Select, quando faccio l'Update non devo impostare in qualche modo un comando di Update specificando la tabella e i campi da aggiornare?

Jeremy Profilo | Guru

>Ma una domanda: quando faccio la fill, devo in precedenza impostare
>la query di Select, quando faccio l'Update non devo impostare
>in qualche modo un comando di Update specificando la tabella
>e i campi da aggiornare?

Si ..... devi valorizzare le CommandText di UPDATE,INSERT,DELETE del dataadapter.....altrimenti il metodo Update non esegue nulla.
Scusa se non l'ho indicato prima.....

Facci sapere..
Ciao


Luigi3 Profilo | Junior Member

Il comando di Insert dovendo fare questi insert in automatico dovro' scriverlo in questa maniera?
INSERT INTO ShoppingCart
(BookId, CustId, Quantity)
Values (@bookid, @custid, @quantity)

Cioè i valori li scrivo con: @nomecapo?

Grazie ancora!!

Jeremy Profilo | Guru

>Il comando di Insert dovendo fare questi insert in automatico
>dovro' scriverlo in questa maniera?
>INSERT INTO ShoppingCart
> (BookId, CustId, Quantity)
>Values (@bookid, @custid, @quantity)

Si...ma potresti lasciar fare tutto al CommandBuilder
Guarda questo link se ti può essere utile.
http://support.microsoft.com/kb/308507/it

Facci sapere...
Ciao

Luigi3 Profilo | Junior Member

Grazie per il prezioso aiuto, ho risolto un po' di problemi ma adesso ho un errore sull'Update.
Nel link che mi hai mandato c'era questo esempio:

//Modify the value of the CustName field.
CustomersDataSet.Tables["Customers"].Rows[0]["CustName"] = "Jack";

//Post the data modification to the database.
da.Update(CustomersDataSet, "Customers");

e io ho questa situazione:

rollDataSet.Tables["RollExt"].Rows[j][29] = "1";

daRoll.Update(rollDataSet, "RollExt");

Pero' ottengo questo errore:
Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.

che da quello che ho visto sembrerebbe significare che non ci sono record modificati e quindi non c'e' nulla da aggiornare sul database.

Non ho impostato il comando di update, ma ho utilizzato: OleDbCommandBuilder cmdBuilder;

Dove sbaglio?

Jeremy Profilo | Guru

Ciao Luigi.
Ho paura di averti aiutato a fare solo più confusione.
Vediamo se riesco a rimediare.

Nella riga di codice prima di fare l'Update(o subito dopo l'utilizzo del commandbuilder), prova a scrivere le seguenti righe di codice.
MessageBox.show(da.UpdateCommand.CommandText) MessageBox.show(da.InsertCommand.CommandText) MessageBox.show(da.DeleteCommand.CommandText)

In questo modo dovresti vedere il lavoro eseguito dal CommandBuilder.
Controlla sopratutto che le commandText si riferiscano alla tabella al quale vuoi apportare le modifiche.

Secondo poi, il campo che tenti di modificare, a che tipo corrisponde nella tabella del Db??

Facci sapere....
Ciao


Luigi3 Profilo | Junior Member

No, che confusione, mi sei stato d'aiuto.

Allora i tre comandi sono tutti a Null.
daRoll.UpdateCommand.CommandText
daRoll.InsertCommand.CommandText
daRoll.DeleteCommand.CommandText

Significa che devo impostarli io? E come?

Per quanto riguarda la modifica dei campi del datatable ci sono riuscito ;)

Jeremy Profilo | Guru

>Significa che devo impostarli io? E come?
Scrivendo la query come da te indicato qualche post più su.
Prova così:
INSERT INTO ShoppingCart(BookId, CustId, Quantity) Values(@bookid, @custid, @quantity) UPDATE ShoppingCart SET BookId=@bookid,CustId=@custid,Quantity=@quantity WHERE BookId=@bookid DELETE FROM ShoppingCart WHERE BookId=@bookid

Se non riesci ...fatti sentire .... proverò a mettere giù un esempio che rispecchia il tuo scenario.

Facci sapere...
Ciao

Luigi3 Profilo | Junior Member

che calvario... credevo fosse piu' semplice del previsto.

Allora imposto questa istruzione:
daRoll.UpdateCommand.CommandText = "UPDATE Roll_Ext SET Modified=@modified,Added=@added,Plant=@plant WHERE Index=@index";

quando viene eseguita va in catch con il seguente errore:
Object reference not set to an instance of an object.

Da premettere che prima faccio questo:
OleDbCommandBuilder cmdBuilder;
cmdBuilder = new OleDbCommandBuilder(daRoll);

attendo tuoi lumi...

Jeremy Profilo | Guru

Ciao Luigi
L'errore che ricevi, probabilmente, dipende dal fatto che gli oggetti InsertCommand,UpdateCommand,etc...sono a Nothing...quindi non vi è un'istanza dell'oggetto.
Entro domani sera faccio delle prove e ti posto i risultati...così sto calvario finisce

A domani.....
Ciao

Luigi3 Profilo | Junior Member

Ce l'ho fatta!!!!!!! Queste erano le istruzioni che mancavano:

daRoll.UpdateCommand = new OleDbCommand();

daRoll.UpdateCommand.Parameters.Add(new OleDbParameter("@modified", OleDbType.VarChar, 50,"Modified"));
daRoll.UpdateCommand.Parameters.Add(new OleDbParameter("@added", OleDbType.VarChar, 50,"Added"));
daRoll.UpdateCommand.Parameters.Add(new OleDbParameter("@Plant", OleDbType.VarChar, 50,"Plant"));
daRoll.UpdateCommand.Parameters.Add(new OleDbParameter("@index", OleDbType.Integer,50,"Index"));

Ho dovuto inserire i parametri che vado a modificare e il parametro inserito nella where dell'update.

e questa è l'istruzione di update per far aggiornare la tabella in Access:

daRoll.UpdateCommand.CommandText = "UPDATE Roll_Ext SET Modified=@modified,Added=@added,Plant=@Plant WHERE Index=@index";

Nella tabella deve esserci un campo chiave, io ho dovuto aggiungere il campo index che faccio riempire in automatico con un valore incrementale.

Che dire, mille grazie a Jeremy, il suo aiuto è stato fondamentale!!!

Mi viene in mente un'altra domanda: ma se aggiungo delle righe al datatable nel codice, quando poi devo aggiornare la tabella su access, devo fare sempre l'UPDATE? O devo anche definire il comando di Insert.

Jeremy Profilo | Guru

Ciao Luigi..
Sono contento che ci sei riuscito.

>Mi viene in mente un'altra domanda: ma se aggiungo delle righe
>al datatable nel codice, quando poi devo aggiornare la tabella
>su access, devo fare sempre l'UPDATE? O devo anche definire il
>comando di Insert.

Devi definire anche l'InsertCommand

Facci sapere....
Ciao


Luigi3 Profilo | Junior Member

Se ho 32 campi devo riscrivere 32 righe come questa???

daRoll.InsertCommand.Parameters.Add(new OleDbParameter("@index", OleDbType.Integer,50,"Index"));

che pizza......

Altra cosa:
scorro la solita tabella, se trovo un determinato record, me lo memorizzo in un'altro DataTable:

DataTable dtToadd = new DataTable(); //creo una nuova dataTable
DataRow drtoAdd = dtToadd.NewRow(); //in questa nuova Datatable creo una nuova dataRow
drtoAdd = rollDataSet.Tables["RollExt"].Rows[j]; //ne faccio la copia
drtoAdd[30] = "1"; //modifico un campo
dtToadd.Rows.Add(drtoAdd); //la aggiungo al nuovo dataTable

Risultato:
Errore: "This row already belongs to another table."



Jeremy Profilo | Guru

Ciao Luigi.
L'errore che ricevi sta a significare che l'oggetto DataRow appartiene già ad un dataTable, quindi.....devi creare un altro oggetto DataRow conforme alla struttura del nuovo DataTable(al quale poi apparterrà senza darti errori), popolarlo e poi aggiungerlo al nuovo DataTable

Facci sapere....
Ciao

Luigi3 Profilo | Junior Member

Approfitto della tua pazienza...

All'interno del codice, memorizzo in un datatable alcune righe che poi vado ad inserire nella tabella access.
E' possibile effettuare una select (che contiene campi somme e Group by) direttamente sul dataTable?

Jeremy Profilo | Guru

Lo puoi fare con LINQ....ma al momento non so ancora esserti di aiuto(sto ancora studiando)....o per lo meno....potrei passarti del codice senza potertelo spiegare......nel senso che lo prendo dal libro e te lo copio pari pari.
Altrimenti puoi comunque crearti un bel ciclo For Each....Next con il quale puoi prelevare i valori dei campi che ti servono.

Facci sapere...
Ciao.

Luigi3 Profilo | Junior Member

Se riesci passamelo pure.

Il problema e' che devo effettuare una query su quel dataTable che mi raggruppi alcuni record e mi calcoli la somma di alcuni campi, quindi se ne leggo uno alla volta non credo di riuscirci.

Grazie!!!

Jeremy Profilo | Guru

Ok ... dammi tempo stasera.
Ciao

turboivan Profilo | Newbie

Ciao come hai risolto questo problema?


//Se ho 32 campi devo riscrivere 32 righe come questa???
//
//daRoll.InsertCommand.Parameters.Add(new OleDbParameter("@index", OleDbType.Integer,50,"Index"));
//
//che pizza......

Sono al tuo stesso punto è sto cercando un modo per non scrivere 40 parameters.add ...

se mi puoi aiutare

Grazie Ivan

Luigi3 Profilo | Junior Member

Guarda alla fine ho risolto in altra maniera, ma la prima strada è stata proprio quella di aggiungere a mano tutti i campi per il command.
E' un po' troppo macchinosa come procedura, altrimenti devi utilizzare direttamente i datareader e agire in altra maniera.

turboivan Profilo | Newbie

Temevo questa tua risposta ...

Ti posso chiedere cosa hai fatto per non utilizzare i parameters?

Grazie

Luigi3 Profilo | Junior Member

Ho trovato una soluzione che è una via di mezzo:
ho un database access sul quale lavorare: all'inizio del programma mi leggo tutte le tabelle che mi servono e le metto in altrettanti DataTable in memoria. Per le operazioni che devo fare ho bisogno solo all'inizio di questa lettura, poi faccio le mie opreazioni e alla fine scrivo direttamente sulle tabelle access tramite delle ExecuteNonQuery di stringe query preparate.

Spero di essere stato chiaro....
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-2023
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5