VB + MySQL: DataGridView update/refresh live bzw. in realtime

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von dennis1702.

    VB + MySQL: DataGridView update/refresh live bzw. in realtime

    Hallo Zusammen,

    zuerst mal vorweg, es ist das ERSTE MAL, dass ich mich innerhalb eines Forums bezüglich Probleme/Fragen zu Programmieren/Datenbanken wende.
    Habt ein wenig nachsicht, wenn ich mich evtl. unklar ausdrücke oder bei beantworteten Sachen nicht direkt antworte (Familie hat bei mir immernoch vorrang ;) )

    So wo das geklärt ist, kommen wir zu meinem Anliegen:

    Ich habe ein bisher kleines "Tool" welches sich aber WEIT vergrößern soll, sobald ich das Problem lösen kann, Grundlegend könnte man sagen es ist ein ToDo/Aufgaben Programm, welches aber im späteren Verlauf auch eine Art Ticketsystem (Ähnlich zu Jira z.B.) bekommen soll. Aber soweit ist es noch nicht. Zu Anfang meldet sich jeder erstmal an und dafür habe ich bisher in VB einen Anmeldebildschirm gebastelt, sieht so aus -> Siehe Bild Anmeldefenster.jpg
    Dieses Anmeldefenster meldet den Benutzer (Je nachdem wer es ist) an einer MySQL Datenbank im Remoteverfahren an.

    VB.NET-Quellcode

    1. Imports MySql.Data.MySqlClient
    2. Public Class Form1
    3. Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
    4. System.Diagnostics.Process.Start("mailto:dennis@fahrdienst-rhein-main.de")
    5. End Sub
    6. Private Sub OK_Click(sender As Object, e As EventArgs) Handles OK.Click
    7. con = NewCon
    8. con.ConnectionString = "server=123456789url.de;userid=user;password=passwort;database=ramar;SslMode=none"
    9. Try
    10. con.Open()
    11. Dim Query As String
    12. Query = "select * from ramar.user where username='" & usertextbox.Text & "' and password='" & passwordtextbox.Text & "' "
    13. cmd = New MySqlCommand(Query, con)
    14. con.Close()
    15. Catch ex As MySqlException
    16. MessageBox.Show(ex.Message)
    17. Finally
    18. con.Dispose()
    19. End Try
    20. If usertextbox.Text = "User1" And passwordtextbox.Text = "Passwort" Then
    21. Call Ralf()
    22. ElseIf usertextbox.Text = "User2" And passwordtextbox.Text = "Passwort" Then
    23. Call Kristin()
    24. ElseIf usertextbox.Text = "User3" And passwordtextbox.Text = "passwort" Then
    25. Call Vera()
    26. ElseIf usertextbox.Text = "User4" And passwordtextbox.Text = "passwort" Then
    27. Call Hasan()
    28. ElseIf usertextbox.Text = "UserA" And passwordtextbox.Text = "passwort" Then
    29. Call Admin()
    30. ElseIf usertextbox.Text = "" Or passwordtextbox.Text = "" Then
    31. MsgBox("Benutzer- und Passwortfeld dürfen nicht leer sein!", MsgBoxStyle.Critical, "ACHTUNG!!!")
    32. Else
    33. MsgBox("Falscher Benutzername oder Passwort!", MsgBoxStyle.Critical, "ACHTUNG!!!")
    34. End If
    35. End Sub
    36. Private Sub UserA()
    37. UserAForm.Show()
    38. Me.Hide()
    39. End Sub
    40. Private Sub User1()
    41. User1Form.Show()
    42. Me.Hide()
    43. End Sub
    44. Private Sub User2()
    45. User2Form.Show()
    46. Me.Hide()
    47. End Sub
    48. Private Sub User3()
    49. User3Form.Show()
    50. Me.Hide()
    51. End Sub
    52. Private Sub User4()
    53. User4Form.Show()
    54. Me.Hide()
    55. End Sub
    56. Private Sub Cancel_Click(sender As Object, e As EventArgs) Handles Cancel.Click
    57. Me.Close()
    58. End Sub
    59. End Class


    Datenbank liegt mittels Portweiterleitung im Internet. Die Version von MySQL ist 5.5, falls das wichtig ist.
    Nachdem sich User oder Admin angemeldet hat, hat man eine Art Menü für (später irgendwann) mehrere Tabellen/Funktionen.
    In diesem Fall nehmen wir als Beispiel mal die Personal Tabelle, wo 2-3 User neues Personal in einem Unternehmen anlegen können. Form -> Siehe Bild PersonalFenster.jpg
    Die Linken TextBoxen ignorieren wir vorerst (Habe zuerst mit der ListView Option gebaut).
    Hier mal der Code den ich bisher in der Personalform habe:

    VB.NET-Quellcode

    1. Imports MySql.Data.MySqlClient
    2. Public Class PersonalForm
    3. ''Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. ''Try
    5. 'FALSCH -> sql = "INSERT INTO 'ramar'.'Personal'('Vorname','Nachname','Abteilung','E-Mail','Telefon') VALUES('" & TextBox1.Text & "','" & TextBox2.Text & "','" & TextBox3.Text & "','" & TextBox4.Text & "','" & TextBox5.Text & "')"
    6. 'RICHTIG v'
    7. '' sql = "INSERT INTO `ramar`.`Personal` (`Vorname`, `Nachname`, `Abteilung`, `E-Mail`, `Telefon`) VALUES ('" & TextBox1.Text & "','" & TextBox2.Text & "','" & TextBox3.Text & "','" & TextBox4.Text & "','" & TextBox5.Text & "')"
    8. 'ConnectionRoot()
    9. '' cmd = New MySqlCommand(sql, NewCon)
    10. '' cmd.ExecuteNonQuery()
    11. '' MsgBox("Person angelegt")
    12. ''Catch ex As Exception
    13. '' MsgBox(ex.Message)
    14. ''Finally
    15. '' cmd.Dispose()
    16. '' NewCon.Close()
    17. '' End Try
    18. 'Me.PersonalTableAdapter.Fill(Me.RamarData.Personal)
    19. '' End Sub
    20. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    21. Me.Close()
    22. End Sub
    23. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    24. TextBox1.Text = ""
    25. TextBox2.Text = ""
    26. TextBox3.Text = ""
    27. TextBox4.Text = ""
    28. TextBox5.Text = ""
    29. End Sub
    30. 'Private Sub PersonalBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs)
    31. 'Me.Validate()
    32. 'Me.PersonalBindingSource.EndEdit()
    33. 'Me.PersonalTableAdapter.Update(Me.RamarData.Personal)
    34. 'End Sub
    35. Private Sub PersonalForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    36. 'TODO: Diese Codezeile lädt Daten in die Tabelle "RamarData.Personal". Sie können sie bei Bedarf verschieben oder entfernen.
    37. Me.PersonalTableAdapter.Fill(Me.RamarData.Personal)
    38. 'Me.PersonalDataGridView.DataSource = Me.RamarData.Personal
    39. 'Me.PersonalDataGridView.Refresh()
    40. If RamarData.HasChanges(DataRowState.Added) Then
    41. Me.Validate()
    42. PersonalBindingSource.EndEdit()
    43. Me.PersonalTableAdapter.Update(Me.RamarData.Personal)
    44. End If
    45. If RamarData.HasChanges(DataRowState.Deleted) Then
    46. Me.Validate()
    47. PersonalBindingSource.EndEdit()
    48. Me.PersonalTableAdapter.Update(Me.RamarData.Personal)
    49. End If
    50. If RamarData.HasChanges(DataRowState.Modified) Then
    51. Me.Validate()
    52. PersonalBindingSource.EndEdit()
    53. Me.PersonalTableAdapter.Update(Me.RamarData.Personal)
    54. End If
    55. Timer1.Start()
    56. 'If Me.InvokeRequired Then
    57. 'Me.Invoke(Sub() 'lampda
    58. 'End Sub)
    59. 'Else
    60. 'End If
    61. End Sub
    62. Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    63. Me.Validate()
    64. PersonalBindingSource.EndEdit()
    65. Me.PersonalTableAdapter.Update(Me.RamarData.Personal)
    66. End Sub
    67. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    68. Me.PersonalDataGridView.DataSource = Me.RamarData.Personal
    69. Me.PersonalDataGridView.Refresh()
    70. End Sub
    71. Private Sub PersonalDataGridView_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles PersonalDataGridView.CellContentClick
    72. End Sub
    73. Private Sub ButtonNew_Click(sender As Object, e As EventArgs) Handles ButtonNew.Click
    74. PersonalBindingSource.AddNew()
    75. End Sub
    76. 'Private Sub Tableupdate()
    77. 'If RamarData.HasChanges(DataRowState.Added) Then
    78. ' New rows have been added to the dataset, add appropriate code.
    79. 'Else
    80. ' No new rows have been added to the dataset, add appropriate code.
    81. 'End If
    82. 'End Sub
    83. End Class


    Wie man sieht, ich habe ein paar Sachen bisher ausprobiert (Siehe auskommentierte Zeilen).
    Mein Problem ist nur, entweder es muss ein Aktualisieren Button gedrückt werden, um das DataGridView aktuell zu halten oder ich brauche einen Timer, der aber beim Aktualisieren nicht jedesmal los meckert, dass bei der Eingabe von neuem Personal kein "NULL" zulässig ist.
    Die Daten, die ich im BindingSource eingebe, werden, man glaubt es kaum, direkt ins DataSet geschrieben. Dies konnte ich anhand des ersten Test's mit dem Timer beim Verändern der bereits eingetragenen Daten erkennen, dass der Timer direkt aktualisiert hat. Das geht allerdings nicht, wenn man neues Personal anlegt, da das Dataset ja dann direkt erstmal eine "NULL" Zeile erhält und sobald der Timer durchläuft erkennt er Fehleingaben.

    Folgendes ist für mich wichtig, bzw. würde ich gerne erreichen: Eine Automatische aktualisierung des DataGridViews, sobald ein User eine Zeile einträgt, sodass auch alle anderen Benutzer des Tools erkennen "Aha, da ist was eingetragen worden, bzw. ah, der Kollege X hat bereits den neuen Kollegen Y angelegt". Im Idealfall (Für Technisch unbegabte Mitarbeiter) ohne einen Akualisierungsbutton. Halt Automatisch.

    Meine Frage an euch ist jetzt, gibt es eine Methode, wo sowas möglich ist? Ich habe bereits dutzende Stunden im Netz mit der Suche verbracht und muss jetzt einfach hier fragen, so unangenehm wie es mir auch ist, weil ich die befürchtung habe, dass es sowas ganz banales ist, wo ich aber nicht drauf gekommen bin. ?(

    Ich danke euch schon mal im Voraus und entschuldige mich, falls einiges an Text hier total unnötig ist. ;)

    Gruß Dennis

    EDIT: Ich vergaß eine Frage: Wo liegt eigentlich der Unterschied zwischen DataGridView.Refresh() und Me.PersonalDataTable.Update(...)??
    Bilder
    • Anmeldefenster.jpg

      558,29 kB, 1.920×1.080, 37 mal angesehen
    • PersonalFenster.jpg

      536,49 kB, 1.920×1.080, 43 mal angesehen
    Programmieren sollte für Personen, die was ordentliches machen wollen, eine Leidenschaft sein. Ansonsten entsteht nur Müll und davon haben wir bereits genug in der Gesellschaft. :D
    Wie heißt es so schön, willkommen im Forum.

    Wenn ich deinen bisherigen Code so anschauen, wird das bald nicht mehr wartbar.
    Du hast pro User eine namentliche Sub und ein Form. Warum? Wenn ein User hinzukommt oder wenn einer wegfällt musst du alles umschreiben.
    Du solltest deine Controls vernünftig benennen, dann hast du mehr Überblick.

    Deine ganze Anmeldung ist offen für SQL Injection und strotzt vor, bereits erwähnten, hard coded Kram.

    Den Unterschied zwischen dem Update und dem Refresh hätte man schon nach kurzer Suche in der MSDN finden können.

    Zu dem Update der anderen Clients wenn ein User schon einen Eintrag erfasst hat, woher sollen die anderen Clients etwas davon wissen? Dafür benötigt man einen Server Dienst der aktiv die Clients über Änderungen benachrichtigt. Zum Beispiel SignalR.

    Grundlegend fehlt es an so viel, dass das Erlernen der Basics eine gute Idee wäre.
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.
    Hier einige Tipps meinerseits:
    1. Benenne deine Controls immer sauber
    2. Lagere den DB Zugriff in eine separate Klasse aus
    3. Nutze die SQL Command Parameters damit man keine SQL injection durchführen kann
    4. Arbeite Objektorientiert
    5. Lerne wie man Forms korrekt instanziiert
    6. Obligatorisch: Arbeite Option Strict On (falls noch nicht passiert)

    Dein Code ist so wie er jetzt ist früher oder später nicht mehr wartbar (Spaghetticode). Ich würde die automatische aktualisierunge erstmal komplett weg lassen. Das kann man alter immer noch einbauen wenn das Grundgerüst steht. Lieber nen Time laufen lassen der informativ anzeigt das es nen neues Ticket gibt. Dann kann der User immer noch entscheiden ob er manuell die Daten neu läd...
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Danke MrTrebron und danke mrMo für eure Antworten.

    Ich stimme euch beiden zu, der Code ist wahrlich sehr wüst. Lag daran, dass ich mehrfach das Projekt gestartet habe (immer wieder anders) und meist an diesem Problem gescheitert bin und den Aufbau immer neu gestaltet habe.
    Daher könnte es nun sein, dass ich einiges erstmal total besch*** geschrieben habe (unübersichtlich) weil ich dieses Problem erstmal überwinden wollte.
    Aber ich werde mich die Tage hinsetzen und mal alles übersichtlich gestalten.

    Den Unterschied zwischen dem Update und dem Refresh hätte man schon nach kurzer Suche in der MSDN finden können.


    Ja natürlich, da stimme ich dir zu, allerdings habe ich VIELE Seiten gefunden, wo sowohl das eine, als auch das andere für dasselbe Benutzt wurden. Daher wollte ich hier mal fragen.

    Du hast pro User eine namentliche Sub und ein Form. Warum? Wenn ein User hinzukommt oder wenn einer wegfällt musst du alles umschreiben.


    Das liegt daran das meine Idee war, dass jeder User seine eigene Oberfläche mit wichtigen Funktionen für diesen User hat. Da ja jeder was anderes braucht.
    Sozusagen, braucht die Abteilung Fuhrpark keine Aufgabenverteilung an Abteilung IT, da diese nicht direkt zusammen arbeiten (zumindest bei mir), Geschäftsleitung darf Grundsätzlich alles und kann jede Funktion nutzen. Abteilung Buchhaltung soll eine Zeiterfassung für die Mitarbeiter machen können, sowas soll aber Abteilung Fuhrpark, IT und andere nicht. Das war dann für mich das schnellste Gerüst.

    Also werde ich am Montag erstmal ein wenig umbauen und würde mich dann hier noch mal melden.
    Vielen Dank nochmal.
    Programmieren sollte für Personen, die was ordentliches machen wollen, eine Leidenschaft sein. Ansonsten entsteht nur Müll und davon haben wir bereits genug in der Gesellschaft. :D
    Also zunächst solltest du dir ein Datenmodell überlegen. Zudem Strukturen, Einstellungen, Funktionen die dein Programm nachher haben soll. Du brauchst also ein KONZEPT. Ohne das, codest du wild irgendwas zusammen... Also: Papier und Stift und Programm konzeptionieren.

    Was brauche ich?
    - Benutzer
    - Benutzerrollen
    - Einstellungen
    - DB Zugriff
    - Tickets
    - Ticket Status (neu, bearbeitung, erledigt, usw.)
    - und und und

    Ich würde den Benutzern, wie @MrTrebron schrieb, mit Benutzerrollen arbeiten. Über die Rolle steuerst du dann was wer machen darf (löschen, bearbeiten, usw.) und was wer sehen kann (Auswertungen, Einstellungen, Fuhrpark, usw.).

    Zudem rate ich davon ab, alles hart rein zu programmieren. Versuche dein Programm einstellbar zu machen. Ist zwar mehr zum programmieren, dafür bist du hinten raus flexibler...
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Papier und Stift, klingt wie Back to the Roots. Aber hast schon recht.
    Prinzipiell habe ich den Anfang ja, bis auf Benutzerrollen und Einstellungen. Da bin ich ja aber durch MrTrebron drauf gebracht worden, dass so zu machen.
    Werde mir da mal eine Aufstellung bzw. das Konzept zusammenstellen und erst dann mal alles überflüssige (wie das Auskommentierte z.B.) raus werfen. So wird das ganze dann hoffentlich aufgeräumter.
    Den DB-Zugriff habe ich btw. in eine eigene Klasse ausgelagert, aber habe im Anmeldeformular irgendwie noch die Anmelderoutine ausgeschrieben (k.A. warum).
    Wie gesagt, ich schreib erstmal auf, wie es nach der Anmeldung weiter gehen soll und sobald das Konzept fertig steht kehre ich zurück.
    Programmieren sollte für Personen, die was ordentliches machen wollen, eine Leidenschaft sein. Ansonsten entsteht nur Müll und davon haben wir bereits genug in der Gesellschaft. :D