Hallo an alle VB.netler,
Ich steh vor einem Problem, dessen Lösung mich nicht ganz erreicht. Nicht mal ünber google, auch wenn ich Hinweise gefunden habe.
Ich fülle ein DataGridView per Abfrage auf eine SQL Server 2008 DB. Diese Abfrage beinhaltet INNER JOINS auf mehrere Tabellen. Das funktioniert auch.
Wenn ich nun aber Datensatzänderungen in die DB zurückschreiben will, beginnt bei mir der Horror.
Ein dynamisches UpdateCommand des SqlAdapters kann wohl nicht für DataSources, die aus einer Abfrage auf mehrere Tabellen bestehen, ausgeführt werden. Leuchtet mir bis zu einem bestimmten Punkt ein.
ABER: wie kann ich nun hier ein UPDATE ausführen, dass die, im DataGridView gemachten Änderungen an Datensätzen auch in die DB zurückgeschrieben werden??
Ich weiß, evtl. schwer nachzuvollziehen, daher ein Beispiel:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
DBcon.myQueryStr = "SELECT Auftrag.ID, Auftrag.AuNr AS 'Auftrag', Auftrag.Datum, Kunde.Firma AS 'Auftraggeber', Auftrag.vPLZ AS 'von PLZ', Auftrag.vOrt AS 'von Ort', " & _
"Auftrag.vLand AS 'von Land', Auftrag.nPLZ AS 'nach PLZ', Auftrag.nOrt AS 'nach Ort', Auftrag.nLand AS 'nach Land', Auftrag.Sendung, Auftrag.Gewicht, Einheit.Einheit, " & _
"Auftrag.FRPreis AS 'Frachtpreis', Untern.Firma AS 'Frachtführer', Auftrag.TUPreis, Auftrag.Rechnung, Auftrag.Gewinn, Auftrag.Kennz AS 'Kennzeichen', " & _
"Auftrag.DispoNr, Auftrag.ErfGef AS 'Erfasst & Gefaxt', Status.ID AS 'Status'" & _
"FROM Auftrag"
DBcon.sqlAdapter.SelectCommand = New SqlClient.SqlCommand(DBcon.myQueryStr, DBcon.con)
'DBcon.sqlAdapter.SelectCommand = New SqlClient.SqlCommand(DBcon.myQueryStr, DBcon.con)
DBcon.sqlAdapter.Fill(DBcon.sqlSet, "Auftrag")
'DBcon.myTable = DBcon.sqlSet.Tables("Auftrag")
'DBcon.mybinding.DataSource = DBcon.myTable
'GlobVars.uf.Controls("dgvAUF").DataSource = DBcon.myTable
If DBcon.sqlSet.Tables("Auftrag").Rows.Count = 0 Then
NoDSFound("Transportaufträge")
Exit Sub
End If
GlobVars.uf.Text = "Transportaufträge"
GlobVars.uf.Show()
GlobVars.uf.Controls("dgvAUF").DataSource = DBcon.sqlSet.Tables("Auftrag")
GlobVars.uf.Controls("dgvAUF").DataSource = DBcon.mybinding
GlobVars.uf.Controls("dgvAUF").Columns("ID").Visible = False
GlobVars.uf.Controls("dgvAUF").Columns(DBcon.sqlSet.Tables("Auftrag").Columns.Count - 1).Visible = False
GlobVars.uf.Controls("dgvAUF").AllowUserToAddRows = False
GlobVars.uf.Controls("dgvAUF").ReadOnly = True
SetStaColors("dgvAUF")
GlobVars.uf.Controls("lbCOU").Text = GlobVars.uf.Controls("dgvAUF").RowCount
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Falls noch mehr info benötigt wird, einfach sagen.
Vielen Dank schon mal für die Hilfe
Grüße
Kai
Programmieren - alles kontrollieren 4.941 Themen, 20.708 Beiträge
SORRY, der Code muss heißen.......
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub miAUF_TRA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles miAUF_TRA.Click
On Error GoTo fehler
If DBcon.DBstate = 1 Then
GlobVars.uf = ufAUF
If IsNothing(GlobVars.uf.Controls("dgvAUF").DataSource) Then
DBcon.myQueryStr = "SELECT Auftrag.ID, Auftrag.AuNr AS 'Auftrag', Auftrag.Datum, Kunde.Firma AS 'Auftraggeber', Auftrag.vPLZ AS 'von PLZ', Auftrag.vOrt AS 'von Ort', " & _
"Auftrag.vLand AS 'von Land', Auftrag.nPLZ AS 'nach PLZ', Auftrag.nOrt AS 'nach Ort', Auftrag.nLand AS 'nach Land', Auftrag.Sendung, Auftrag.Gewicht, Einheit.Einheit, " & _
"Auftrag.FRPreis AS 'Frachtpreis', Untern.Firma AS 'Frachtführer', Auftrag.TUPreis, Auftrag.Rechnung, Auftrag.Gewinn, Auftrag.Kennz AS 'Kennzeichen', " & _
"Auftrag.DispoNr, Auftrag.ErfGef AS 'Erfasst & Gefaxt', Status.ID AS 'Status'" & _
"FROM Auftrag " & _
"LEFT JOIN Einheit ON Auftrag.FKEinheit = Einheit.ID LEFT JOIN " & _
"Untern ON Auftrag.FKFRFührer = Untern.UnNr LEFT JOIN " & _
"Status ON Auftrag.FKStatus = Status.ID LEFT JOIN " & _
"Kunde ON Auftrag.FKKunde = Kunde.KdNr " & _
"ORDER BY Auftrag.AuNr"
DBcon.sqlAdapter.SelectCommand = New SqlClient.SqlCommand(DBcon.myQueryStr, DBcon.con)
DBcon.sqlAdapter.Fill(DBcon.sqlSet, "Auftrag")
If DBcon.sqlSet.Tables("Auftrag").Rows.Count = 0 Then
NoDSFound("Transportaufträge")
Exit Sub
End If
GlobVars.uf.Text = "Transportaufträge"
GlobVars.uf.Show()
GlobVars.uf.Controls("dgvAUF").DataSource = DBcon.sqlSet.Tables("Auftrag")
GlobVars.uf.Controls("dgvAUF").DataSource = DBcon.mybinding
GlobVars.uf.Controls("dgvAUF").Columns("ID").Visible = False
GlobVars.uf.Controls("dgvAUF").Columns(DBcon.sqlSet.Tables("Auftrag").Columns.Count - 1).Visible = False
GlobVars.uf.Controls("dgvAUF").AllowUserToAddRows = False
GlobVars.uf.Controls("dgvAUF").ReadOnly = True
SetStaColors("dgvAUF")
GlobVars.uf.Controls("lbCOU").Text = GlobVars.uf.Controls("dgvAUF").RowCount
Else
Exit Sub
End If
Else
MsgBox("Es besteht keine Datenbankverbindung!")
End If
Exit Sub
fehler:
MsgBox(Err.Description)
MsgBox(Err.Number)
End Sub
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Wie würde denn überhaupt Deine Strategie aussehen, wenn mehrere Zeilen geändert wurden? Spätestens wenn z.B. ein Kunde in mehreren Zeilen auftaucht, dann kracht das. Ganz böse wird es wenn dann noch an beiden Zeilen konkurrierende Änderungen vorgenommen werden...
Die Zeilen sind doch durch die ID eindeutig, oder? von dem her sollte der UpdateCommand in der Lage sein jede zeile upzudaten. Wäre die Bindung an das datagridview eine einzige tabelle ohne die Joins, würde es wohl funktionieren.
Ein Kunde kann auch in mehreren Zeilen stehen, das ist nicht unique. wo wäre denn der krachpunkt?
Meinst Du die Auftrag.ID?
In gewisser Weise sind die Zeile schon eindeutig.
Ein Kunde kann auch in mehreren Zeilen stehen, [...] wo wäre denn der krachpunkt?
Genau dort!
Beispiel:
Auftrag.ID=1, ..., Kunde.ID=1, Name=Neo3000
Auftrag.ID=2, ..., Kunde.ID=2, Name=Borlander
Auftrag.ID=3, ..., Kunde.ID=1, Name=Neo3000
Jetzt wird in Auftrag.ID=3 der Kunde geändert:
Auftrag.ID=1, ..., Kunde.ID=1, Name=Neo3000
Auftrag.ID=2, ..., Kunde.ID=2, Name=Borlander
Auftrag.ID=3, ..., Kunde.ID=1, Name=Neo4000
Welcher Name ist nun der Richtige für Kunde 1?
Jetzt wird in Auftrag.ID=1 und 3 der Kunde geändert:
Auftrag.ID=1, ..., Kunde.ID=1, Name=Neo3001
Auftrag.ID=2, ..., Kunde.ID=2, Name=Borlander
Auftrag.ID=3, ..., Kunde.ID=1, Name=Neo4000
Welcher Name ist nun der Richtige für Kunde 1?
Problem klar?
Gruß
Borlander
Da hast du recht, so würde ich auch Schwierigkeiten stoßen.
Allerdings besteht genau hier eine kleine "Besonderheit" die ich erstmal erläutern muss damit man versteht was ich meine. Also:
In meiner DB gibt es eine Tabelle nur mit Kundendaten (KdNr, Firma, Adresse, Tel, usw) und auch eine mit Aufträgen die eine Spalte beinhaltet in der nicht der "Kundenname" bzw. "Firmenname", sondern die "KdNr" steht.
In meinem DataGridView binde ich die Tabelle "Aufträge", lasse aber über die Joins nicht die "KdNr" sondern den "Firmenname" anzeigen. In den Quelldaten der Tabelle "Aufträge" steht aber weiterhin die "KdNr".
Wird nun eine Zeile geändert, z.B. Auftrag.ID=1, gibt der Benutzer hier den Firmenname ein, z.B. "Bosch AG" und beim Klick auf "Speichern" soll dann über ein SELECT die "KdNr" aus der Tabelle "Kunden" ermittelt werden (sofern der Kunde existiert) und DIESE dann in die DB gespeichert werden. Ich denke somit sollte ich den von dir zurecht beschriebenen Problem aus dem Weg gehen.
Der Grund für so ein "gewurschtel", ich wollte damit möglichst wenig Datenredundanzen in der DB erzeugen.
Dass nicht z.B der Firmenname des Kunden einmal in der Tabelle "Kunden" UND dann nochmal in der Tabelle "Aufträge" gespeichert wird.
Wenn ich aber da dabei bin murgs zu machen, einfach sagen ;-).
Das würde ich nun nicht gerade als "Besonderheit" bezeichnen. Das ist gängige Praxis (Stichwort "Normalisierung")...
Die Besonderheit sehe ich eher darin, dass Du unbedingt diese gejointe Tabelle komplett editierbar machen willst. Das erscheint mir nicht unbedingt sinnvoll. Änderungen an der Tabelle Firma würde ich tendenziell auch eher nur über einen eigenen Dialog erlauben. Da drückst du beim bearbeiten einmal zu oft die Tab Taste und schreibst weiter, und schon ist der Firmeneintrag kaputt...
Wird nun eine Zeile geändert, z.B. Auftrag.ID=1, gibt der Benutzer hier den Firmenname ein, z.B. "Bosch AG" und beim Klick auf "Speichern" soll dann über ein SELECT die "KdNr" aus der Tabelle "Kunden" ermittelt werden (sofern der Kunde existiert) und DIESE dann in die DB gespeichert werden. Ich denke somit sollte ich den von dir zurecht beschriebenen Problem aus dem Weg gehen.
Was passiert wenn mehrere Zeilen geändert wurden bevor auf Speichern gedrückt wurde?
Btw.: Was machst Du eigentlich mit Firmen/Kunden deren Name sich irgendwann mal ändert? ;-)