Problem beim Update eines typisieren Datasets

  • VB.NET

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

    Problem beim Update eines typisieren Datasets

    Hallo,

    ich habe in VisualStudio 2019 Prof ein typisiertes Dataset erstellt:

    Dateset:
    ' Projekt: Hinzufügen neues Element: Dataset
    ' Per Server-Explorer Tabelle hinzufügen und im Dataset bearbeiten

    ' Die Tabelle heißt _Testtabelle

    ' Datenbankfelder sind
    ' K nvarchar(50)
    ' P nvarchar(50)
    ' S int

    Neue Datensätze per typisiertem Dataset erzeuge ich so:

    Quellcode

    1. Dim ds As New Testdataset()
    2. Dim ta As New TestdatasetTableAdapters._TesttabelleTableAdapter()
    3. Dim row As Testdataset._TesttabelleRow = ds._Testtabelle.New_TesttabelleRow()
    4. ta.Fill(ds._Testtabelle)
    5. row.K = "K 5555"
    6. row.P = "Old value"
    7. ds._Testtabelle.Add_TesttabelleRow(row)
    8. ta.Update(ds._Testtabelle)


    das funktioniert auch.
    Zum Ändern nutze ich folgendes:

    Quellcode

    1. Dim ds As New Testdataset()
    2. Dim ta As New TestdatasetTableAdapters._TesttabelleTableAdapter()
    3. ta.Fill(ds._Testtabelle)
    4. Dim row As Testdataset._TesttabelleRow = ds._Testtabelle(0)
    5. row.BeginEdit()
    6. If row.K.Equals("K 5555") Then
    7. row.P = "New value"
    8. End If
    9. row.EndEdit()
    10. ta.Update(ds._Testtabelle)


    Eine Fehlermeldung bekomme ich nicht, allerdings funktioniert das auch nicht.
    Kann jemand helfen?

    Danke im Voraus
    Wenn du sagst "das funktioniert nicht", dann denke ich meinst du die Datenbank übernimmt nicht die Änderungen?
    Schreib mal vor dem ta.Update jeweils

    VB.NET-Quellcode

    1. Dim test = row.RowState
    Der sollte im ersten Fall Added sein und im zweiten Modified. (Kannst stattdessen auch in row direkt nachgucken natürlich)
    Den Rest macht dann entsprechend der Update -Befehl automatisch bzw. meckert der auch entsprechend (und das meiner Erfahrung nach meist nicht zu knapp).

    Außerdem sieht was du machst sehr umständlich aus. Aber ohne Gerüst, mag ich auch nicht wirklich Vorschläge für Änderungen machen.
    Zum Beispiel ist mir nicht klar warum du bei jedem Hinzufügen und Ändern Fillst, bzw. das ganze DataSet neu erstellen musst.

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

    Hallo,

    @Haudruferzappeltnoch (cooler Name):
    ich kann mir das morgen wieder ansehen und melde mich entsprechend.

    @Erfinder des Rades: Tatsächlich kam kein Fehler ohne PrimaryKey, allerdings habe ich in einem anderen Beitrag den Hinweis von dir gefunden, das zu tun.
    Mit PrimaryKey habe ich keine Änderung feststellen können.

    Also ich beschäftige mich schon längere Zeit mit Datenbankprogrammen.
    Bisher habe ich alles per SqlClient abgewickelt, sowas wie das hier:

    Quellcode

    1. Dim con As New SqlConnection
    2. Dim cmd As New SqlCommand
    3. Dim reader As SqlDataReader
    4. Try
    5. con = New SqlClient.SqlConnection
    6. con.ConnectionString = ...
    7. cmd.Connection = con
    8. cmd.CommandText = "SELECT X
    9. FROM X
    10. WHERE X = @p1 "
    11. cmd.Parameters.AddWithValue("@p1", "X")
    12. con.Open()
    13. reader = cmd.ExecuteReader
    14. Do While reader.Read
    15. Loop
    16. ...


    Das geht, auch asynchron, unter zuhilfenahme von Listen und Linq ganz gut. Allerdings muß ich mich um die Updates selber kümmern, wenn sich Daten ändern.
    Da habe ich es für eine gute Idee gehalten, mich mal mit Datasets zu beschäftigen und bin jetzt auf der Suche nach einem guten Standard.
    Das, was ihr hier von mir gelesen habt, ist aus Gal....eo O..n B...s, scheint mir aber nicht ganz optimal.

    Vielen Dank bisher für eure Kommentare
    Hallo,

    ich mache das jetzt so:

    Quellcode

    1. For Each row As Testdataset._TesttabelleRow In ds._Testtabelle.Where(Function(x) x.K = "K 6666")
    2. row.BeginEdit()
    3. row.P = "janz New value"
    4. row.EndEdit()
    5. Next


    ...und wie immer gilt: Wenn man es richtig macht, funktioniert das auch

    Tableadapter.Fill führe ich jetzt 1x beim Start aus,
    das update per Tableadapter mache ich dann ganz zum Schluß 1x.

    Vielen Dank für eure Hilfe

    mfg
    A
    @Haudrauf...
    Da das Feld K das Feld mit dem Primärschlüssel ist,
    brauche ich das FindBy... nicht, werde ich mir aber merken.

    @Erfinder...
    Ich habe mir die Definition von BeginEdit und EndEdit angesehen und es schien mir richtig,
    die zu nutzen. Aber ich werde diese mal weglassen und beobachten, was passiert.

    Danke für eure Hilfe
    VG
    A
    Definition von BeginEdit und EndEdit angesehen...
    Huch - die Doku dazu habich ja noch nie gelesen!
    Da steht was von Events suspendieren und von Datenkonsistenz suspendieren. Ich hab nu klein Experiment gemacht, aber das DataTable.ColumnChanged-Event wird nicht suspendiert.
    Dabei ist mir aufgefallen, dass diese Member von Intellisense nicht vorgeschlagen werden beim Coden.
    Das würde ich als Hinweis verstehen, dass DataRow.BeginEdit/EndEdit nur für die interne Verwaltung im Dataset von Belang sind (zB im Zusammenhang mit Databinding), und eher nicht vorgesehen, von Programmierern benutzt zu werden.
    (.AcceptChanges() ist übrigens auch so ein Kandidat, von dem man besser die Finger lässt.)

    Aber gerne du mach auch Experimente, und berichte.

    Ah - zB das DataTable.RowChanged-Event wird verzögert bis zum EndEdit.
    Macht Sinn, wenn man in derselben DataRow mehrere Änderungen vornehmen will, und dieses Event abonniert hat.
    Wie gesagt: in Databinding-Szenarien ist das Relevant, wenn man in einem Datagridview eine Zeile editiert - da werkelt solch im Hintergrund - (und Programmierer sollten sich eher raushalten)
    BeginEdit und EndEdit benutze ich aus einem einfachen Grund nicht, nämlich, dass nie etwas nicht ohne die funktioniert hat. Sozusagen unbekannte Funktionen für mich.

    AcceptChanges und RejectChanges benutze ich gleichermaßen. RejectChanges um Benutzereingaben zu korrigieren. Und AcceptChanges weil ich nicht immer Änderungen irgendwohin schreiben muss.
    Hi ihr,

    gem. Definition benutzt man AcceptChanges, um eine Datarow in einem z.B. Tableadapter zu modifizieren, also um zu "speichern" (das jetzt nicht zu wörtlich nehmen)
    Ich sehe den tieferen Sinn noch nicht. Das mache ich mit den Aggregatfunktionen doch auch, oder?

    Mal von vorne:

    Ich habe ein Dataset, welches die Abfrage enthält.

    In der Klasse mache ich folgendes:

    VB.NET-Quellcode

    1. Private ds As New Testdataset()
    2. Private ta As New TestdatasetTableAdapters._TesttabelleTableAdapter()
    3. ta.Fill(ds._Testtabelle)


    1. Ich deklariere ein Dataset
    2. Ich deklariere einen TableAdapter, der auf das Dataset zeigt
    3. Ich fülle den TableAdapter mit den entsprechenden Daten

    So, jetzt habe ich einen Tableadapter, der im Prinzip einer stark typisierten Tabelle entspricht
    und den ich mit einfachsten Mitteln manipulieren kann,

    Z.B. für ein Select:

    VB.NET-Quellcode

    1. For Each item As Testdataset._TesttabelleRow In ds._Testtabelle '.Where(Function(x) x.K <> String.Empty)
    2. Console.WriteLine("{0},{1}", item.K, item.P)
    3. Next


    Z.B. für ein Insert:

    VB.NET-Quellcode

    1. Dim row As Testdataset._TesttabelleRow = ds._Testtabelle.New_TesttabelleRow()
    2. row.K= "K Irgendwas"
    3. ds._Testtabelle.Add_TesttabelleRow(row)


    Damit habe ich eine neue Zeile im Tableadapter

    Z.B. für ein Edit:

    VB.NET-Quellcode

    1. For Each row As Testdataset._TesttabelleRow In ds._Testtabelle.Where(Function(x) x.K = "K Sonstwas")
    2. row.Pos = "New value"
    3. Next


    Damit habe ich einen geänderten Wert im Tableadapter.(Das habe ich ausprobiert, das ist auch so)

    Z.B. für ein Delete:

    VB.NET-Quellcode

    1. For Each row As Testdataset._TesttabelleRow In ds._Testtabelle.Where(Function(x) x.K = "K 6666")
    2. row.Delete()
    3. Next



    Und am Ende speichere ich das ganze zurück:

    VB.NET-Quellcode

    1. ta.Update(ds._Testtabelle)


    Scheint mir alles simpel und vollständig oder übersehe ich etwas?

    VG
    A
    Du weisst vmtl. bereits, dass man ein typDataset viel einfacher ohne Datenbank abspeichert und lädt?
    Einfach in eine Datei. Das hat grosse Vorteile an Portabilität, Performance, ResourcenSparsamkeit.
    Und das Heckmeck mit DB und DataAdapter kann man immer nachträglich noch dranbasteln.
    Aber erstmal sollte man sich das Aufsparen für später - es gibt im Bereich Datenmodellierung und Databinding eine Menge Dinge vorrangig zu erlernen.
    Habe dazu auch Tuts im DatenbankBereich eingestellt, und auch auf CodeProject.