Come salvare dati modificati in DataGrid?

mercoledì 22 dicembre 2004 - 10.00

Steve71 Profilo | Newbie

Salve a tutti, mi sono affacciato da poco sul mondo .Net e ho parecchie lacune da colmare.

Una (enorme) riguarda proprio l'inserimento/modifica dei dati sul db (SQL Server) da una DataGrid in una WindowsForm.
Mi spiego meglio: io visualizzo i dati di una tabella del db da DataSet in una DGR e l'utente ha la possibilità di modificare/aggiungere/rimuovere i record poichè readonly=false.

Come posso salvare nel db questi cambiamenti?

Apprezzerei molto qualche esempio di codice o link esplicativo... Grazie!

giorgiodipietro Profilo | Junior Member

Per caricare questi dati dal db sul dataset hai usto un dataadapter giusto?

I casi sono due:

-se hai creato il dataadapter da progettazione (creazione guidata) è sufficiente utilizzare il comando Adapter.Update e impostargli come argomento la tabella dal quale salvare i dati (es DataAdapter.Update(Dataset1.tabella1)), in quanto la creazione guidata crea già tutti i comandi necessari

-se hai creato il dataadapter da codice è leggermente più complesso, ma neanche più di tanto...l'unico problema è che non hai già impostati i vari DeleteCommand, InsertCommand e UpdateCommand necessari per salvare...
utilizza il seguente codice...

'dichiari il necessario

Dim Connessione as New SqlClient.SqlConnection(<qua devi inserire la tua stringa di connessione>)
Dim Slt As New SqlClient.SqlCommand()
Dim Adapt as New SqlClient.SqlDataAdapter()
Dim CmdBld as New SqlClient.SqlCommandBuilder()

'imposto l'adapter

Slt.Connection = Connessione
Slt.CommandText = <istruzione select>
Adapt.SelectCommand = Slt
CmdBld.DataAdapter = Adapt
Adapt.DeleteCommand = CmdBld.GetDeleteCommand
Adapt.InsertCommand = CmdBld.GetInsertCommand
Adapt.UpdateCommand = CmdBld.GetUpdateCommand

'e finalmente Aggiorni il db

Adapt.Update(<Tabella>)

Steve71 Profilo | Newbie

Ti ringrazio, sei molto gentile. Ora il codice del mio Form di test è:

Private Sub Test_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim cn As New SqlClient.SqlConnection(DataManager.GetConnString)
Dim cmd As New SqlClient.SqlCommand
Dim da As New SqlClient.SqlDataAdapter
Dim cmdBld As New SqlClient.SqlCommandBuilder
Dim ds As New DataSet

cmd.Connection = cn
cmd.CommandText = "SELECT * FROM Devices"
da.SelectCommand = cmd
cmdBld.DataAdapter = da

da.DeleteCommand = cmdBld.GetDeleteCommand
da.InsertCommand = cmdBld.GetDeleteCommand
da.UpdateCommand = cmdBld.GetUpdateCommand

da.Fill(ds, "Devices")

dgrTest.DataSource = ds.Tables("Devices")

da.Update(ds.Tables("Devices"))

End Sub

I dati vengono correttamente visualizzati sulla DataGrid, ma le modifiche continuano ad essere ignorate...
Forse mi sono perso qualcosa: QUANDO dovrebbero venire chiamati i comandi GetDeleteCommand, GetDeleteCommand e GetUpdateCommand?
O meglio, quando deve essere eseguito il da.Update(ds.Tables("Devices")) ?
Devo forse aggiungere un Button <save> e associargli qualche finzione di aggiornamento?

Ciao & grazie!

giorgiodipietro Profilo | Junior Member

Esatto...perchè il tuo eseguibile con il codice che hai scritto, quando la form appare e dunque scatena l'evento load, lui carica e salva subito...ignorando le future modifiche....

Quindi nell'evento load carichi e basta il tuo dataset (magari prima del Fill(dataset), fai un FillSchema(dataset) cosìcchè lui prima imposta la tabella e poi la carica con il Fill(dataset)), crea un Button <salva> o <aggiorna> e lì fai l'Update con tutti Get...command precedenti.

Un ultimo consiglio la connessione e la select dichiarale a livello di modulo così non devi più chiamarle, o se non è un eseguibile troppo complesso dichiara direttamente e poi imposti quando serve.

Ciao

Steve71 Profilo | Newbie

Sei un grande... FUNZIONA TUTTO!!!
Dimmi se ti sembra corretto o se è migliorabile:

Dim cn As New SqlClient.SqlConnection(DataManager.GetConnString)
Dim cmd As New SqlClient.SqlCommand
Dim da As New SqlClient.SqlDataAdapter
Dim cmdBld As New SqlClient.SqlCommandBuilder
Dim ds As New DataSet

Private Sub Test_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

' [CUT di altre menate]

EditDatas("Devices")

End Sub

Private Sub EditDatas(ByVal dbTableName As String)

cmd.Connection = cn
cmd.CommandText = "SELECT * FROM " & dbTableName
da.SelectCommand = cmd
cmdBld.DataAdapter = da

da.DeleteCommand = cmdBld.GetDeleteCommand
da.InsertCommand = cmdBld.GetInsertCommand
da.UpdateCommand = cmdBld.GetUpdateCommand

da.FillSchema(ds, SchemaType.Source)
da.Fill(ds, dbTableName)

dgrEditData.DataSource = ds.Tables(dbTableName)

End Sub

Private Sub btnSaveData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveData.Click

da.Update(ds.Tables("Devices"))
dgrEditData.Update()

End Sub

Ora mi piacerebbe caricare -manualmente da codice, per forza di cose- in una combobox i nomi delle tabelle, in modo da passarlo come parametro alla EditDatas(nomeTabella) affinchè con una sola dgr sia possibile modificare diverse tabelle.
Possibile secondo te?!
Dovrei passare il nomeTabella al pulsante... a meno che... potrei usare la SelectedValue! Uhmmmm...

GRAZIE INFINITE, intanto!

giorgiodipietro Profilo | Junior Member

Possibilissimo...

...non ho capito bene...tu vuoi caricare la combo con tutte le tabelle del db, ma non da codice giusto?

Steve71 Profilo | Newbie

No, non di TUTTE le tb, solo alcune... ho pensato a due possibilità:

1) add da codice dei nomi delle tb visualizzabili/modificabili, ma mi pare poco pratico nel caso se ne debbano aggiungere

2) creo una ulteriore tb con i nomi delle tb visualizzabili/modificabili, ma richiederebbe a sua volta un gestore...
...a meno che non sia QUELLA DI DEFAULT! Ecco, penso che proverò così.

Ti faccio sapere,
un saluto e GRAZIE ancora!

Steve71 Profilo | Newbie

Dunque, ho aggiunto la tb nel db e ho popolato la combobox:

Dim sql As String = "SELECT * FROM _TablesList ORDER BY TableName"
Dim dt As DataTable = DataManager.GetDataTable(sql)

cboTablesList.DataSource = dt
cboTablesList.ValueMember = "TableName"
cboTablesList.DisplayMember = "Description"

Purtroppo sto incontrando un inconveniente che non riesco ad aggirare!
Al caricamento del Form, subito dopo aver popolato la combobox, viene richiamato l'evento selectedindexchanged:

Private Sub cboTablesList_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboTablesList.SelectedIndexChanged
EditDatas(Convert.ToString(cboTablesList.SelectedValue))
End Sub

Tutto normale, tranne per il fatto che SelectedValue risulta essere "{System.Data.DataRowView}" invece di un nome di tabella, e quindi la sucessiva SELECT * FROM [tabella] va a pallino.

Il bello è che DENTRO al {System.Data.DataRowView} i valori giusti CI SONO, li ho visti in debug!
Ma come li tiro fuori?!

giorgiodipietro Profilo | Junior Member

cdoTableList è la combo?

- se sì devi usare "selctedItem" e non "selectedvalue"

-se no

giorgiodipietro Profilo | Junior Member

cdoTableList è la combo?

- se sì devi usare "selctedItem" e non "selectedvalue"

- se no dimmi cos'è

Ciao e Buon Natale

Steve71 Profilo | Newbie

'so problema mi sta facendo sclerare... non riesco ad uscirne!!!

La combobox CboTablesList viene popolata nel Form_Load da questa Sub:

Private Sub FillCboTablesList()

Dim sql As String = "SELECT * FROM _TablesList ORDER BY TableName"
Dim dt As DataTable = DataManager.GetDataTable(sql)
cboTablesList.DataSource = dt
cboTablesList.ValueMember = "TableName"
cboTablesList.DisplayMember = "Description"

End Sub

Tutto ok, efettivamente i record vencono caricati e si vedono perfettamente nella tendina.
Ma appena metto qualcosa nella SelectedIndexChanged le cose vanno male:

Private Sub cboTablesList_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboTablesList.SelectedIndexChanged

MsgBox(Convert.ToString(cboTablesList.SelectedItem))
' MsgBox(Convert.ToString(cboTablesList.SelectedValue))

End Sub

Se mi faccio visualizzare il valore passato da SelectedItem al caricamento del Form, mi mostra 4 volte {System.Data.DataRowView} prima di passare i valori giusti,
se uso SelectedValue mi arriva 2 volte, poi procede correttamente.
Solo che dovrei passare quella stringa ad una SELECT * FROM [...] che ovviamente si incazza.

Ho persino tentato una cosa tipo:
If not Convert.ToString(cboTablesList.SelectedItem) = "{System.Data.DataRowView}" Then
EditDatas(Convert.ToString(cboTablesList.SelectedItem))
End If

Ma pare NON sia comunque "uguale"........... ARGHH!!!

Steve71 Profilo | Newbie

OK, ok... ne sono uscito. Non sarà elegante, ma funziona!

Nella Form_Load popolo la combobox:

Private Sub FillCboTablesList()

Dim sql As String = "SELECT * FROM _TablesList ORDER BY TableName"
Dim dt As DataTable = DataManager.GetDataTable(sql)

cboTablesList.DataSource = dt
cboTablesList.ValueMember = "TableName"
cboTablesList.DisplayMember = "Description"

End Sub

Al cambio di indice, carico la DataGrid; poichè il Form_Load già scatena un SelectedIndexChanged, al pimo Load si presenta la lista delle tabelle editabili. Da notare l'IF ...

Private Sub cboTablesList_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboTablesList.SelectedIndexChanged
If (Convert.ToString(cboTablesList.SelectedValue) <> "System.Data.DataRowView") And Convert.ToString(cboTablesList.SelectedValue) <> "" Then
EditDatas(Convert.ToString(cboTablesList.SelectedValue))
End If

End Sub

Carico nella DataGrid la tabella da editare, selezionata in automatico la prima volta e dall'uente in seguito

Private Sub EditDatas(ByVal dbTableName As String)

cmd.Connection = cn
cmd.CommandText = "SELECT * FROM " & dbTableName
da.SelectCommand = cmd
cmdBld.DataAdapter = da

da.DeleteCommand = cmdBld.GetDeleteCommand
da.InsertCommand = cmdBld.GetInsertCommand
da.UpdateCommand = cmdBld.GetUpdateCommand

da.FillSchema(ds, SchemaType.Source)
da.Fill(ds, dbTableName)

dgrEditData.DataSource = ds.Tables(dbTableName)

End Sub

Dopo le modifiche salvo i dati della DataGrid nel db, passando di nuovo il nome della tabella selezionata.

Private Sub btnSaveData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveData.Click

da.Update(ds.Tables(Convert.ToString(cboTablesList.SelectedValue)))
dgrEditData.Update()

End Sub

CIAO!!!
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-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5