System.Data.ConstraintException bei .Fill mit DBExtension

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von DianonForce.

    System.Data.ConstraintException bei .Fill mit DBExtension

    Moin Forum ich benötige mal wieder Eure Hilfe.

    Eins vor weg, es liegt vermutlich nicht an den DBEx, ich bin vermutlich nur zu doof sie richtig zu benutzen.

    Ich versuche im Load Event eines Forms mit hilfe der DBEx die Tabellen eines Dataset zu befüllen. Hier mal das Script dazu:

    VB.NET-Quellcode

    1. Dim adpDispatching = New DatasetAdapter(
    2. MySql.Data.MySqlClient.MySqlClientFactory.Instance,
    3. My.Settings.dispatchingConnectionString,
    4. ConflictOption.OverwriteChanges)
    5. Db_serviceticket.Adapter(adpDispatching).Register(Me, True)
    6. With Db_serviceticket
    7. .Fill(.tbl_service_ticket_status, .tbl_user_web)
    8. .tbl_serviceticket.Fill("WHERE status <> 14 AND status <> 39 AND status <> 102 ORDER BY Datum DESC")
    9. .Fill(.tbl_serviceticket_detail)
    10. End With


    Ich bekomme hier dann folgende Fehlermeldung
    System.Data.ConstraintException wurde nicht behandelt.
    Message=Einschränkungen konnten nicht aktiviert werden. Mindestens eine Zeile enthält Werte die die Einschränkungen non-null, unique or foreign-key verletzen.


    Problem ist, dass zwischen tbl_serviceticket.id und tbl_serviceticket_detail.ticket_id eine 1 zu n Beziehung besteht.

    Wenn ich die Where Klausel entferne funktioniert der Fill ohne Probleme. Da ich die Daten mit Status 14,39,102 aber nicht benötige und diese ca 90% aller Daten ausmachen würde ich diese ungerne laden wenn ich sie eh nie nutze. Gibt es einen Trick wie ich den Tableadapter für tbl_serviceticket_detail nur mit Daten befülle deren ticket_id auch in der der befüllten tbl_serviceticket vorkommen?
    Deine Frage geht bzgl. DBEx wohl v.a. @ErfinderDesRades. Aber hier ein Spekulatius von mir: Deine Tabellen enthalten Zeilen, die auf eine der ausgeschlossenen Servicetickets verweisen. Klar, dass dann gemeckert wird. Dann müsstest Du wohl auch die davon abhängigen Tabellenzeilen ausschließen.
    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 schrieb:

    ... Deine Tabellen enthalten Zeilen, die auf eine der ausgeschlossenen Servicetickets verweisen. Klar, dass dann gemeckert wird. Dann müsstest Du wohl auch die davon abhängigen Tabellenzeilen ausschließen.

    Jop, genau das ist mein Problem und das sollte ansich auch die Frage sein, wie mach ich das?

    Bei PHP würd ich jetzt per For Each durch die Datensätze des Results der tbl_servicetickets gehn und mir die dazugehörigen tbl_servicetickets_details besorgen, aber ich hatte gehofft mir das bei der schicken Lösung der DBEx irgendwie zu sparen.

    EDIT: OK, ich glaube ich habe der DBEx da zu viel Eigeniteligenz zugetraut: Wen ich EdR's-Tutorial richtig verstanden habe, muß ich es genau so machen wie ich es bei PHP gemacht hätte. Mit Hilfe von parentRow.FillChildTables beim wechseln der currentRow die Child Table jeweils neu befüllen. Ansich auch logisch, keine Ahnung wie ich auf die vermessene Idee kam, dass das die DBEx bei .Fill selber auf die Kette bekommt, nur das aus den Child Tables zu laden was in der Parent Table existiert.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DianonForce“ ()

    Irgendwie läufts heute ned bei mir, laufe grade in den nächsten Fehler rein und verstehe es nicht.

    Habe versucht wie hier von EdR erklärt die tbl_serviceticket_detail on the fly zu befüllen

    VB.NET-Quellcode

    1. Private Sub Test_Load(sender As Object, e As EventArgs) Handles Me.Load
    2. Dim adpDispatching = New DatasetAdapter(
    3. MySql.Data.MySqlClient.MySqlClientFactory.Instance,
    4. My.Settings.dispatchingConnectionString,
    5. ConflictOption.OverwriteChanges)
    6. Me.Db_serviceticket.Adapter(adpDispatching)
    7. With Db_serviceticket
    8. .Fill(.tbl_service_ticket_status, .tbl_user_web)
    9. .tbl_serviceticket.Fill("WHERE status <> 14 AND status <> 39 AND status <> 102 ORDER BY Datum DESC")
    10. End With
    11. End Sub
    12. Private Sub Tbl_serviceticketBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles Tbl_serviceticketBindingSource.CurrentChanged
    13. Dim rwServiceticket = Tbl_serviceticketBindingSource.At(Of tbl_serviceticketRow)()
    14. If rwServiceticket.Null Then Return
    15. With Db_serviceticket
    16. rwServiceticket.FillChildTables(.tbl_serviceticket_detail)
    17. End With
    18. End Sub


    leider bekomme ich jetzt folgende Meldung:
    Eine Ausnahme vom Typ "MySql.Data.MySqlClient.MySqlException" ist in MySql.Data.dll aufgetreten, doch wurde diese im Benutzercode nicht verarbeitet.

    Zusätzliche Informationen: There is already an open DataReader associated with this Connection which must be closed first.


    Leider ist mir atm überhaupt nicht klar wo denn dieser 'allready open' DataReader sein soll. Hat grade jemand einen Knüppel mit dem er mir einen Hinweis reinhauen kann?

    EDIT: OK, auch hier scheint mir die Where-Klausel von .tbl_serviceticket.Fill wieder einen Strich durch die Rechnung zu machen. Ohne diese bekomme ich keine Fehlermeldung beim Start.
    EDIT 2: Kann es sein, dass es mit der Verarbeitungszeit der .tbl_serviceticket.Fill zu tun hat, lege ich das FillChildTables auf einen Button und nicht auch das CurrentChanged Event funktioniert es auch.

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

    DianonForce schrieb:

    Zusätzliche Informationen: There is already an open DataReader associated with this Connection which must be closed first.
    möglicherweise kann man das auch iwo konfigurieren, dass auf eine Connection mehrere DataReader zulässig sind.

    Was vorsich geht ist glaub: Die ParentTable serviceticket befüllt sich, und sobald der erste Datensatz reinkommt changed die angebundene BindingSource. Sodass während die Parent befüllt wird gleichzeitig die Childs befüllt zu werden versuchen.
    Du kannst versuchen, das zu entzerren wie folgt:

    VB.NET-Quellcode

    1. Private Sub Tbl_serviceticketBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles Tbl_serviceticketBindingSource.CurrentChanged
    2. Dim rwServiceticket = Tbl_serviceticketBindingSource.At(Of tbl_serviceticketRow)()
    3. If rwServiceticket.Null Then Return
    4. BusyDelay.SetCallback(Sub()rwServiceticket.FillChildTables(Db_serviceticket.tbl_serviceticket_detail))
    5. End Sub


    (und tu dir einen Gefallen: entferne diese unsinnige tbl_-Prefixe aus deiner Datenbank. Man darf vorraussetzen, dass es Tabellen sind, was da in deine DB drinne ist, und selbst wenn du da noch was anneres haben solltest, wäre das über DbExtensions nicht ansprechbar)