Update einer Row im typisierten DataSet

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

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von OliverSte.

    @OliverSte: Kurze Frage zum Anfang des Threads: Das Update machst Du ja mit RowDelete und RowAdd. Ginge es nicht, dass Du Dir jene Row schnappst und dort die Zeilenwerte einfach aktualisierst?

    VB.NET-Quellcode

    1. If ICaDts.SD_frau.Where(Function(x) x.Id_ICa = rwICa.Id_ICa).Count = 1 Then
    2. Dim rwCheck = ICaDts.SD_frau.Where(Function(x) x.Id_ICa = rwICa.Id_ICa)(0)
    3. rwCheck.frau_Vorname = rwDS04_frau.frau_Vorname
    4. rwCheck.frau_Nachname = rwDS04_frau.frau_Nachname
    5. '...
    6. Else
    7. ICaDts.SD_frau.AddSD_frauRow(rwICa, rwDS04_frau.frau_Vorname, rwDS04_frau.frau_Nachname)
    8. End If

    ggf. ließe sich das ja notfalls auch für andere Updates generalisieren
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed
    Ja, das ginge, aber scheint mir sehr viel aufwändiger zu sein. Müsste man ja zusätzlich noch durch die Columns loopen, um es mit EDRs Worten zu sagen ;)
    Ob das bremisch wäre, weiß ich nicht, ich bin Rheinländer, wohne nur hier ;)

    @ErfinderDesRades
    Es gibt immer eine ICaRow, den Master quasi. Die hat BefundRows inner Childtabelle.
    Jetzt kommen neue DS04BefundRows und die sollen an die BefundRows angehängt werden.
    Wenn da aber welche sind, also BefundRows, dann sollen die mit den neuen DS04BefundRows abgeglichen werden. Bei den Befunden gibt es dazu noch die bef_Nr.
    Da ich für so einen Abgleich kein Werkzeug habe, mache ich Del und Add.

    Über der Update-Schleife der einzelnen Tabellen loope ich durch die DS04 und hole mir jeweils die zugehörige ICaRow. Die brauche ich ja als ForeignKey für die Childtabellen.

    Dann ist ja falsch, die DS04-Befunde durchzuloopen, und die IcaBefunde jede Runde neu zu ermitteln.


    Ja, das gibt mir gerade zu denken. Ich könnte gleich alle BefundRows löschen und alle DS04BefundRows anfügen, fertig.
    Gibt es etwas in der Art?

    VB.NET-Quellcode

    1. ICaDts.SD_befund.Where(Function(x) x.Id_ICa = rwICa.Id_ICa).Remove


    Alternativ muss der Coder etwas umgestellt werden:

    VB.NET-Quellcode

    1. ' alle vorhandenen löschen
    2. Dim rwsCheck = ICaDts.SD_befund.Where(Function(x) x.Id_ICa = rwICa.Id_ICa).ToArray
    3. If (rwsCheck.Length > 0) Then
    4. For i = (rwsCheck.Length - 1) To 0 Step -1
    5. ICaDts.SD_befund.RemoveSD_befundRow(rwsCheck(i))
    6. Next
    7. End If
    8. ' alle neuen anfügen
    9. Dim rwDS04_befund As DS04ausMasc.DS04_befundRow
    10. For Each rwDS04_befund In rwDS04.GetDS04_befundRows()
    11. ICaDts.SD_befund.AddSD_befundRow(rwICa, rwDS04_befund.bef_Nr, rwDS04_befund.bef_Datum, rwDS04_befund.bef_Supervision, rwDS04_befund.bef_Voraufnahmen, rwDS04_befund.bef_Recall, rwDS04_befund.bef_Ergebnis)
    12. Next


    Halt nein, wenn es dann keine DS04BefundRows gibt, habe ich meine Daten verloren ...

    Auch wenn nun nicht immer ALLES im Import ist, sondern der Datenbestand ergänzt wird, muss man die anzufügende Row mit der vorhandenen abgleichen. Das war wahrscheinlich die Intention für die Löschschleife innerhalb des DS04Befund-Loops. Lösche nur das, was gerade neu angeliefert wird. Tja und bei dem Vergleich klemmt es. Da hab ich einfach alles gelöscht.

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

    OliverSte schrieb:

    Jetzt kommen neue DS04BefundRows und die sollen an die BefundRows angehängt werden.
    Ich vermute, du meinst was anneres als du sagst - daher kann man auch keine klare Antwort geben (vmtl. eh nicht).
    Nämlich dass du die Ds04Befunde nicht an die IcaBefundRows anhängen willst, sondern wie gesagt: Mergen.
    Mergen bedeutet: Gibt es zu einem Ds04Befund einen entsprechenden IcaBefund, so soll letzterer mit Werten ersteren aktualisiert werden.
    Gibt es keinen entsprechenden IcaBefund, so soll ein neuer IcaBefund aus den Werten des Ds04Befundes entstehen.
    Mergen hätte in diesem Fall 2 Kruxen:
    1. Es muss eine Definietion von "entsprechend" implementiert sein - nach welchen Spalten ist zu gucken, um zu sagen: "Dieser Ds04Befund entspricht diesem IcaBefund"?
    2. Es muss "aktualisieren" implementiert sein: Welche Werte aussem Ds04 sollen in den Ica geschrieben werden?
    3. Es muss "entstehen" implementiert sein: Welche Werte aussem Ds04 sollen in den neuen Ica geschrieben werden?
    Habe ich das ühaupt richtig verstanden? (Weil gesagt hast du was anderes, nämlich "anhängen".) Dann kann man da weiter machen - mergen ist eine prinzipiell bekannte Dataset-Operation - allerdings nur für ganze DataTables. Also du müsstest ein Spezial-Merge schreiben.



    OliverSte schrieb:

    Dann ist ja falsch, die DS04-Befunde durchzuloopen, und die IcaBefunde jede Runde neu zu ermitteln.
    Ja, das gibt mir gerade zu denken. Ich könnte gleich alle BefundRows löschen und alle DS04BefundRows anfügen, fertig.
    Das hab ich nicht gesagt.
    Einfach was ich gesagt habe, sowas:

    VB.NET-Quellcode

    1. Dim rwDS04_befund As DS04ausMasc.DS04_befundRow
    2. Dim rwsCheck = ICaDts.SD_befund.Where(Function(x) x.Id_ICa = rwICa.Id_ICa).ToArray ' IcaBefunde nur einmal ermitteln reicht
    3. For Each rwDS04_befund In rwDS04.GetDS04_befundRows()
    4. If Not checked Then
    5. checked = True
    6. If (rwsCheck.Length > 0) Then
    7. TextBoxLog.Text = $"{rwsCheck.GetType.ToString.LastRightCut("+")} für {rwICa.kommNr} sind bereits vorhanden und werden aktualisiert.{vbCrLf}{TextBoxLog.Text}"
    8. For i = (rwsCheck.Length - 1) To 0 Step -1
    9. Console.WriteLine($"Lösche {rwsCheck.GetType.ToString.LastRightCut("+")} für kommNr {rwICa.kommNr}")
    10. ICaDts.SD_befund.RemoveSD_befundRow(rwsCheck(i))
    11. Next
    12. End If
    13. rwsCheck = Nothing
    14. End If
    15. ICaDts.SD_befund.AddSD_befundRow(rwICa, rwDS04_befund.bef_Nr, rwDS04_befund.bef_Datum, rwDS04_befund.bef_Supervision, rwDS04_befund.bef_Voraufnahmen, rwDS04_befund.bef_Recall, rwDS04_befund.bef_Ergebnis)
    16. Next
    17. checked = False

    ErfinderDesRades schrieb:

    Ich vermute, du meinst was anneres als du sagst


    In diesem Fall meine ich schon das gesagte, denn es folgt auf das zitierte noch ein Satz:
    Jetzt kommen neue DS04BefundRows und die sollen an die BefundRows angehängt werden. Wenn da aber welche sind, also BefundRows, dann sollen die mit den neuen DS04BefundRows abgeglichen werden.


    Wir meinen schon mal das Gleiche. Ich möchte anhängen und aktualisieren, also mergen.
    Meine Eingangsfrage war, ob es dazu einen Mechanismus gibt. Ja, für DataTables, nein für Rows. Schade. Damit wäre die Frage zunächst beantwortet.
    Nun habe ich aber in dem Thread einiges gelernt, darüber freu ich mich.
    Und es scheint, als sollte man sich mit so einer Merge-Funktion mal auseinandersetzen. Findest du nicht auch, dass das förmlich nach einer Extension schreit?

    Ich habe das Problem, dass ich erstens sowas nicht programmieren kann und zweitens meine Tabellen nicht gleichförmig sind. Ich fürchte, ein einheitliches Merge lässt sich da nicht umsetzen. Es gibt da nämlich sowohl 1:1, als auch 1:n Beziehungen und manche Childrows haben gar kein eindeutiges Identifikationsmerkmal, anhand dessen man sie aktualisieren könnte. Da kann man nur altes löschen und neues anfügen.



    ErfinderDesRades schrieb:

    Das hab ich nicht gesagt. Einfach was ich gesagt habe, sowas:


    Ja, cool, die ICaBefundRows nur EINMAL ermitteln und ggfs. löschen, falls es neue DS04Befunde gibt.
    So kann man sich auch noch den checked= Kram sparen, denn wenn es gelöscht ist ist es gelöscht und ​rwsCheck.Length folglich 0.

    Oder?
    Hmm, kommt darauf an, wie du das "Anhängen" verstehst.
    Ich verstehe darunter, eine Tabelle mit Rows erweitern.
    Die Rows aus DS04_Befund werden an die Tabelle SD_Befund angehängt, die Child von ICa ist.

    Du siehst doch im Code oben ganz genau, was ich da mache.

    VB.NET-Quellcode

    1. ICaDts.SD_befund.AddSD_befundRow(rwICa, ...
    lässt doch eigentlich keinen Spielraum für Spekulationen, oder?

    Übrigens, habe ich den Code noch mal etwas verfeinert.
    Statt

    VB.NET-Quellcode

    1. ​Dim rwsCheck = ICaDts.SD_aufnahme.Where(Function(x) x.Id_ICa = rwICa.Id_ICa).ToArray

    geht ja auch

    VB.NET-Quellcode

    1. ​Dim rwsCheck = rwICa.GetSD_aufnahmeRows()


    und statt

    VB.NET-Quellcode

    1. ​ICaDts.SD_aufnahme.RemoveSD_aufnahmeRow(rwCheck)

    funktioniert

    VB.NET-Quellcode

    1. ​rwCheck.Delete()
    sehr gut.

    OliverSte schrieb:

    Hmm, kommt darauf an, wie du das "Anhängen" verstehst.
    Ich verstehe darunter, eine Tabelle mit Rows erweitern.
    Die Rows aus DS04_Befund werden an die Tabelle SD_Befund angehängt, die Child von ICa ist.
    Jo, da verstehe ich was ganz anneres drunter:
    "Anhängen" ist, im Datensatz einen Verweis auf den ParentDS setzen.

    Und was du meinst: Ds04-Rows in eine Befund-Tabelle füllen - das geht ja garnet. Man kann ja nur BefundRows in eine Befund-Tabelle füllen.

    Das ist ja, was ich sage: Dein Code zeigt was ganz anderes als was du sagst, was du machen willst.


    Wie dem auch sei.
    Mergen ist das auch nicht, wenn du die alten BefundRows alle abräumst, und dann neue hinschreibst.
    Bei Mergen würden bestimmte alte BefundRows unverändert bestehen bleiben, nämlich wenn die neuen Rows keine passende Entsprechung enthalten.

    Aber wenn das für dich ok ist, die ollen wegzuhauen, und neue hinzumachen, dann ist dein Prob ja gelöst.
    Und was du meinst: Ds04-Rows in eine Befund-Tabelle füllen - das geht ja garnet. Man kann ja nur BefundRows in eine Befund-Tabelle füllen.


    ?( Ich fülle doch DS04_Befund-Rows in die SD_Befund-Tabelle. Das geht, mache ich doch die ganze Zeit. Die Tabellen sind ja praktisch gleich, nur die IDs sind andere. Und ja, ich hänge auch an, die rwICa übergebe ich ja eigens zu diesem Zweck an die typisierte Add... Methode.

    Aber, ja, meine Frage ist eigentlich geklärt, ich lösche halt den ganzen Krimskram und fülle die Tabelle mit den Importdaten neu - inkl. Anhängen an die ParentRow ;) Wollte ich mergen, müsste ich das selbst programmieren.

    OliverSte schrieb:

    Ich fülle doch DS04_Befund-Rows in die SD_Befund-Tabelle.
    Nein - gar nicht.
    Wenn du denkst, dass du das tust, dann sitzst du einem grundlegendem Irrtum auf.

    (Ich bin ja völlig eingefahren in typisierte Denkmuster, für mich klingt das regelrecht absurd - so als würdest du sagen: "Ich pflücke Äpfel vom Birnenbaum.")

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Du bist der Wahnsinn ;)
    Ja, was mache ich denn dann? :/

    Ok, ich versuchs mal so: Ich fülle ICa_Befund-Rows mit den Daten einer DS04_Befund-Row.

    VB.NET-Quellcode

    1. firstcheck = True
    2. For Each rwNeu In rwDS04.GetDS04_befundRows()
    3. If firstcheck AndAlso rwICa.GetSD_befundRows().NotNull Then
    4. firstcheck = False
    5. For Each rwAlt In rwICa.GetSD_befundRows()
    6. rwAlt.Delete()
    7. Next
    8. End If
    9. ICaDts.SD_befund.AddSD_befundRow(rwICa, rwNeu.bef_Nr, rwNeu.bef_Datum, rwNeu.bef_Ergebnis)
    10. Next