Update TableAdapter - GridView Clientübergreifend

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von vb_fan.

    Update TableAdapter - GridView Clientübergreifend

    Hallo zusammen und ein Frohes Neues,

    bereits seit längerem schreibe ich an einem größeren Programm inzwischen in der zweiten Version (nicht öffentlich).
    Was mich nach wie vor stört ist das aktualisieren der Daten welche Clientübergreifend angestoßen wird.

    Es gibt mehrere Clients mit dem Programm (verschiedene PC's) und einen Server welche mittels TCP miteinander kommunizieren.
    In meinem Beispiel werden Daten, welche in einer separaten Form durch einen oder mehrere Benutzer erstellt werden, direkt in die Datenbank eingetragen (Insert).
    Gleiches natürlich beim Bearbeiten oder auch Löschen von Zeilen.
    Danach schickt der Client eine Meldung an den Server das ein neuer Eintrag generiert wurde von Person XY, Server schickt an alle angemeldeten Clients ein Update Befehl (normaler String).
    Dieser wird ausgewertet und jeh nach Inhalt des geschickten Strings durch den Server wird auf der Clientseite der TableAdapter neu gefüllt. (Me.Konten_buchungTableAdapter.Fill(Me.Finanz_managerDataSet.konten_buchung))
    Funktioniert, hat nur den großen Nachteil das bei jedem Client die GridView Ansicht springt, da die Daten komplett neu generiert werden.

    Ist es möglich nur die geänderte Row in der Ansicht GridView zu aktualisieren ohne das es komplett springt sondern nur der gewisse Wert oder Zeile geändert wird, wenn ja welche Methoden gibt es, welches Weg müsste man gehen?
    Die Row ist den Clients bekannt, diese wird quasi mit geschickt (z.B Zeile 184).
    In Verwendung habe ich derzeit DevExpress.XtraGrid und MySql.Data.

    Würde mich über Unterstützung freuen.

    Thx.
    @JoJo129
    Quasi die geänderte Zeile welche sich schon in der Datenbank befindet, soll der Client abrufen und in der GridView anzeigen, ohne das der TableAdapter durch das .Fill die Daten einmal komplett holt und dadurch die vorherige Ansicht zerstört. Somit nur die auch geänderte Row die er bereits mitgeteilt bekommt. Zeile 12 wurde in einer Form angepasst, client bekommt die info das es in zeile 12 eine Änderung gegeben hat, updatet derzeit aber alles statt nur die eine Row.

    Beispiel. Ich befinde mich relativ weit unten auf Zeile 369 in der GridView-Ansicht, jetzt werden die Daten bisher einmal komplett neu geladen weil der Server dem Client sagt "Hier sind ja neue Daten vorhanden".
    Client führt im Anschluss derzeit ein TableAdapter.Fill aus, für den Client selbst springt die Ansicht dann komplett nach oben und selektiert die Zeile 0.
    Das ist bei einem Eintrag natürlich weniger Schlimm wenn eine Person daran arbeitet, wenn allerdings 2 - 10 personen das ganze nutzen springt die Tabelle somit bei jedem Update immer wieder nach oben.

    Hoffe es ist so etwas verständlicher, hatte selbst es etwas schwer dies genau zu definieren.
    Also ich habe dafür eine 2. Form dazu benutzt, da steht bloß der alte Text und darunter kann man den neuen Text eingeben.

    Hier einmal mein Code:

    Quellcode

    1. Sub EditSQL(ByVal [Text1] As String, ByVal [new~Text1] As String)
    2. Dim myConnectionString As String
    3. myConnectionString = New SqlConnectionStringBuilder() With {
    4. .DataSource = "Deine_Angabe",
    5. .UserID = "Deine_Angabe",
    6. .Password = "Deine_Angabe",
    7. .InitialCatalog = "Deine_Angabe"
    8. }.ToString()
    9. Text1 = Form1.dgv1.SelectedRows(0).Cells(0).Value.ToString()
    10. Dim sqlcmd As String = "UPDATE [Name der Tabelle] SET [Was willst du ändern] = '" & Text1NEW & "' WHERE [Auswahl] = '" & Text1 & "'"
    11. Dim conn As New SqlConnection(myConnectionString)
    12. Try
    13. conn.Open()
    14. Dim myAdapter As New SqlDataAdapter
    15. Dim command As New SqlCommand(sqlcmd, conn)
    16. command.ExecuteNonQuery()
    17. Catch ex As Exception
    18. MessageBox.Show(ex.Message)
    19. Finally
    20. If conn.State = ConnectionState.Open Then
    21. conn.Close()
    22. conn.Dispose()
    23. End If
    24. End Try
    25. End Sub


    Aber wenn man das dann aktualisiert, wird dein GridView nicht die änderung anzeigen, da müsste man noch eine kleine Funktion einbauen, dass wenn etwas geändert wurde, das die GridView "neu lädt" und man somit direkt die änderung schon sieht.
    Hoffe das hilft dir weiter :thumbsup:

    Edit: Bei Fragen zum Code kannst du auch gerne Fragenstellen.
    Danke dir dafür.

    In der Tat habe ich das bereits auch so umgesetzt bzw. ähnlich.
    Die Daten werden bereits aktualisiert wo ich sie benötige, das passt alles soweit.

    Dein letzter Satz:
    "Aber wenn man das dann aktualisiert, wird dein GridView nicht die änderung anzeigen, da müsste man noch eine kleine Funktion einbauen, dass wenn etwas geändert wurde, das die GridView "neu lädt" und man somit direkt die änderung schon sieht."

    Das ist genau mein Problem, sprich wie lade ich genau nur diese Daten aus der Datenbank um sie dann für jeden anderen Benutzer zu aktualisieren in der Ansicht ohne das die GridView sich hin und her bewegt.
    @Spike Also du möchtest wenn es aktualisiert wurde, das dann direkt nur die zeile angezeigt wird und nicht die gesamte Datenbank?

    Dann versuch mal diesen Code:

    erstmal die Connection und SELECT Abfrage

    Quellcode

    1. Sub/Function()
    2. Dim myConnectionString As String
    3. myConnectionString = New SqlConnectionStringBuilder() With {
    4. .DataSource = "Deine_Angabe",
    5. .UserID = "Deine_Angabe",
    6. .Password = "Deine_Angabe",
    7. .InitialCatalog = "Deine_Angabe"
    8. }.ToString()
    9. Dim sqlcmd As String = "SELECT * FROM [Name der Tabelle] WHERE id = '" & id & "'"
    10. Dim conn As New SqlConnection(myConnectionString)
    11. Try
    12. conn.Open()
    13. Dim command As New SqlCommand(sqlcmd, conn)
    14. command.ExecuteNonQuery()
    15. Catch ex As Exception
    16. MessageBox.Show(ex.Message)
    17. Finally
    18. If conn.State = ConnectionState.Open Then
    19. conn.Close()
    20. conn.Dispose()
    21. End If
    22. End Try


    Und wenn du dann einen Button hast für das UPDATEN, kannst du den folgenden Code mit dazu schreiben

    Quellcode

    1. Dim selectedRow As DataGridViewRow = Form1.dgv1.SelectedRows(0)
    2. Dim id As Integer = CInt(selectedRow.Cells("id").Value)
    3. Sub/Funtion()

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „JoJo129“ ()

    @JoJo129 Nein :thumbdown: ^^
    Es soll schon alles angezeigt werden aber es soll nur die Zeile aktualisiert werde die auch in der Datenbank bereits geändert wurde statt alle Daten neu zu laden.

    Der Benutzer bekommt ja die Info das die Zeile 12 in der GridView geändert wurde und sogar die Info das es sich dabei um die ID 1433 aus der Tabelle buchungen handelt.
    Nun soll die Zeile 12 in der GridView aktualisiert werden mit den Daten aus der Tabelle buchungen welche die ID 1433 hat.

    Der TableAdapter soll nicht komplett neu befüllt werden da dadurch die Anzeige (GridView) springt, sondern es soll im Hintergrund nur die Zeile 12 mit den neuen Daten aus der DB buchungen ID 1433 aktualisiert werden und im Anschluss soll die Ansicht der GridView von Zeile 12 aktualisiert werden.
    Hier aus der Mainform, wenn die entsprechende Nachricht von dem Server ankommt das es einen neuen Eintrag gibt, dann wird untenstehender Code angestoßen.

    VB.NET-Quellcode

    1. 'Aktualisierung Buchungsdaten
    2. If ThreadBuchungAdd = "1" Then
    3. ThreadBuchungAdd = "0"
    4. ucbuchungen.RefreshData_GridView_Buchungen()
    5. End if


    In ucbuchungen geschieht bei aufrufen der Methode folgendes

    VB.NET-Quellcode

    1. Try
    2. 'Daten aus Datenbank finanz_manager verwaltung_buchungen werden neu geladen!
    3. Me.Konten_buchungTableAdapter.Fill(Me.Finanz_managerDataSet.konten_buchung)
    4. 'Wenn Bearbeitet wurde wird nun die aktueller Row wieder ausgewählt!
    5. If EditBuchungStatus = 0 Then
    6. GridView_Buchungen.MoveLast()
    7. ElseIf EditBuchungStatus = 1 Then
    8. If GridView_Buchungen.IsValidRowHandle(SelectedEditRow) Then
    9. GridView_Buchungen.FocusedRowHandle = SelectedEditRow
    10. End If
    11. EditBuchungStatus = 0
    12. End If
    13. Catch ex As Exception
    14. Logger.LogError("Buchungen: Datensätze konnten nicht geladen werden!")
    15. Logger.LogError(ex.Message)
    16. Finally
    17. bsiRecordsCount.Caption = "Datensätze : " & KontenbuchungBindingSource.Count.ToString
    18. Logger.LogInfo("Buchungen: Es wurden insgesamt " + KontenbuchungBindingSource.Count.ToString + " Datensätze geladen!")
    19. End Try


    Derzeit speichere ich die aktuelle Row der Benutzer zwischen vor einem Update, dann werden die Daten neu in den TableAdapter geladen, die Ansicht wird komplett auf "0" gesetzt durch den TableAdapter.
    Anschließend setze ich die Selektierung wieder auf die vorherige Row.
    Anders wusste ich mir bisher nicht zu helfen.
    Die GridControl ist Datengebunden an die Bindingsource. (DataSet)
    Die Daten werden beim Form_load geladen und eingespielt.

    Dein obiger Code aktualisiert doch nur die Daten in der Datenbank selbst?

    Spike schrieb:

    Dein obiger Code aktualisiert doch nur die Daten in der Datenbank selbst?

    Nicht ganz, klar es aktualisiert die Datenbank, aber mit den Code von #Post6 wird dann direkt auch die gesamte Tabelle im GridView angezeigt. Somit sieht man schon die änderungen.
    Jo, das geschieht bei mir alles im Hintergrund.
    Wie gesagt angezeigt wird alles, nur aktualisiert wird ebenfalls alles, was mein Problem auslöst, stattdessen es nur genau die Row aktualisiert.

    Verstehe was du mir damit sagen möchtest, glaube es hilft mir allerdings bei meinem eigentlich Problem nicht.
    Trotzdem vielen Dank.
    Das wird kompliziert.jeder Client muss dann mitgeteilt bekommen, was es neues gibt. Damit er weiss, was er abrufen soll.
    Und "was es neues gibt", - was bedeutet "neu" - im Vergleich zu welchem Zeitpunkt?
    Also muss der Client dem Server mitteilen, was er hat, damit der Server entscheiden kann, was für diesen Client "neu" ist.

    Man könnte wohl einfacher immer alles laden, aber nicht direkt zur Anzeige bringen.
    Sondern im Client erstmal einen Algo drüberlaufen lassen, der den Ist-Stand des Clients mit dem frisch runterrgeladenem Zeugs vergleicht. Und dass der Client sich dann die sachen rauspickt, die er noch nicht hat.