Dataset Beziehungen mit Datenbank ohne Beziehungen

  • VB.NET
  • .NET 4.5

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Dataset Beziehungen mit Datenbank ohne Beziehungen

    Guten Abend,

    ich stehe gerade vor der Aufgabe, eine Anwendung zu entwickeln, welche mit einer bereits vorhanden Datenbank arbeitet. Da diese Datenbank aber sehr suboptimal ist und ich mir daher stundenlanges SQL-Query schreiben sparen wollte, dachte ich mir, ich regel das mittels Dataset und Databinding etc. Ha, denkste.

    Hab also eine kleine lokale Datenbank installiert, mit wenigen Demodaten befüllt und losgehts.
    Neues Projekt, Datenquelle hinugefügt, Beziehungen gesetzt. Anschließend per Designer ein paar gebundene DGV's erstellt und...zack. Beim Erstellen der Fehler "Einschränkungen konnten nicht aktiviert werden. Mindestens eine Zeile enthält Werte die die Einschränkungen non-null, unique or foreign-key verletzen.". Hab dann versucht einige Spalten auf "Unique = False" zu setzen, geht noch immer nicht. Mittels Abfragendesigner des TableAdapters ein paar "WHERE"-Klauseln eingefügt um NULL-Werte zu ignorieren. Geht noch immer nicht, selbe Fehlermeldung (aber auch sehr Schade, dass in der Meldung nicht steht, welche Spalte es genau ist, die den Fehler verursacht, Danke Micro$oft). Habe das ganze jetzt 1 1/2 Stunden versucht irgendwie zu lösen, aber jetzt Frage ich mal die Dataset Experten hier.

    So sieht mein Dataset aktuell aus:


    Ich habe im Anhang mal mein Projekt (ohne meine Versuche das Problem zu beheben) eingefügt sowie die ein Backup der Datenbank (MS-SQL!).

    Ich bedanke mich im Vorraus bei jedem, der mir dazu helfen kann :)

    Grüße
    Dateien
    • ZeitDataset.zip

      (131,33 kB, 5 mal heruntergeladen, zuletzt: )
    • datenbank.sql

      (114,23 kB, 12 mal heruntergeladen, zuletzt: )

    KingLM97 schrieb:

    Schade, dass in der Meldung nicht steht, welche Spalte es genau ist, die den Fehler verursacht, Danke Micro$oft
    Na mal langsam. Probier mal

    VB.NET-Quellcode

    1. YourDataTable.BeginLoadData()
    2. 'Daten einlesen
    3. Try
    4. YourDataTable.EndLoadData()
    5. Catch CEx As System.Data.ConstraintException
    6. For Each Row As Data.DataRow In YourDataTable.Rows
    7. If Not String.IsNullOrEmpty(Row.RowError) Then MessageBox.Show($"{Table.TableName}: {Row.RowError} bei {Row.ToString})")
    8. Next
    9. End Try


    ##########

    Ich hab da mal was gebastelt, was ne entsprechende Ex auslöst und gemeldet abfängt. Dabei kommt raus (inkl. Hinweis im angebundenen DGV):

    Mir ist klar, dass man nicht sinnlos ne Ex abfangen und mit ner MessageBox anzeigen lassen soll, da der Debugger viel mehr Infos hergibt. Aber manchmal sind das so viele, dass man gar nicht weiß, wo man schauen soll. Da macht sich ne gewisse Filterung manchmal ganz gut.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

    jepp - das ist eine Vorgehensweise: Dataset.EnforceConstraints = False setzen, dann lädt das Dataset jeden Mist. Und DGVs zeigen den auch an, aber "bemeckern" ihn mit via ErrorProvider.
    (Das DataTable.BeginLoadData() setzt übrigens ebenfalls intern .EnforceConstraints = False (und . EndLoadData stellts nicht zurück ;( ))

    Die Frage ist nun: Wie kommen die inkonsistenten Daten in die DB? Aufgrund des Fehl-Designs der Original-DB?
    Das wäre allerdings höchst problematisch, denn wie soll man eine stabile Anwendung entwickeln mit korrupten Daten?
    Soll man eine Heuristik basteln, die Müll aussortiert? Aber dabei würde Information verloren gehen.

    ErfinderDesRades schrieb:

    und . EndLoadData stellts nicht zurück
    Das kann ich aber gleich 2x nicht bestätigen. 1. würde mein Konstrukt aus Post#2 doch dann gar keine Exception erzeugen und 2. sagt mein Code: "doch"

    Oder hab ich Dich falsch verstanden?

    ##########

    btw: VS2017CE, FW 4.5; aber selbst mit 3.5 kommt da o.g. raus
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

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

    Hmm - meine Quick-Recherche ergibt eindeutig ein anneres Bild.
    Liegt vielleicht daran, dass ich Begin-/End-LoadData immer gleich auf alle Tabellen des Datasets anwende.
    Also wenn ich eine DatasetDatei einlese zuvor alle Tabellen-Aktivitäten mit .BeginLoadData ruhigstellen, und nachm Laden alle wieder aktivieren.

    Also ich hab da mal erneut ausformuliert, was ich ansonsten in DTS.Fill() gekapselt hab (und noch viel mehr)

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

    Du hast recht. Das ist interessant - da ich auch schon einiges an tDS-Extensions geschrieben habe und einen ähnlichen Aufbau habe (mit BeginLoadData, EndLoadData). Interessant, dass es mir bisher noch nicht um die Ohren geflogen ist:



    ##########

    Hab m.E. das Rätsel lösen können. Es scheint, als müssten die DataTables in umgekehrter Reihenfolge reaktiviert werden, damit EnforceContraints wieder true wird:




    Hab ich gleich erstmal bei meinem Extensions eingebaut.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

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

    Solange das die Kurzform ist von "Ich mach EnforceConstraints = False, lade die Daten, und dann EnforceConstraints = True, damit ich direkt sehen kann, wo der Fehler ist", dann ok. EnforceConstraints dauerhaft auf False zu lassen, führt auf längere Sicht fast zwangsläufig insgeheim zu inkonsistenten Daten, die das System aber einfach verschluckt. Früher oder später würde dann Datenmus draus werden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Ich habe das gestern bisher nur deaktiviert und anschließend ein paar Funktionen geschrieben, die mit dem Dataset arbeiten. Da hat bisher alles funktioniert.

    Wenn ich das nach dem laden der Daten aber wieder aktiviere, dann würde er doch direkt einen Fehler bringen, weil irgendein Key Null ist, oder? Habe das Projekt gerade nicht zur Hand...
    Wenn dem so sein sollte, muss es leider deaktiviert bleiben, denn das eigentliche Programm, dass die Datenbank befüllt etc., arbeitet sehr häufig mit Null-Werten in der Datenbank...was natürlich sehr suboptimal ist.

    KingLM97 schrieb:

    Wenn ich das nach dem laden der Daten aber wieder aktiviere, dann würde er doch direkt einen Fehler bringen, weil irgendein Key Null ist, oder?
    Das ist richtig.
    Wenn ich inkonsistente Daten habe, lade ich (so wie du) die in Dataset mit .EnforceConstraint=False, und zeige sie dann in DGVs an.
    DGV zeigt die RowErrors je Row dann als kleine "ErrorProvider" an.

    Ich hab sogar ein Extra-Control dafür geschrieben, was alle Tables jedes beliebigen (auch untypisierten) Datasets anzeigt.
    Ist halt Bestandteil meiner Helpers-Dlls, und daher kannichs nicht so einfach eben anhängen.
    Aber ich hab glaub auch schon Tuts hochgeladen, wo die Helpers mit drinne sind.

    KingLM97 schrieb:

    denn das eigentliche Programm [...] arbeitet sehr häufig mit Null-Werten in der Datenbank
    Macht ja nix. Wenn es an jenen Stellen sinnvoll ist, dass da NULL drinsteht, dann kannst Du ja in der betroffenen Spalte der DataTable den dazugehörigen Wert ändern: Bei der Eigenschaft NullValue steht standardmäßig (Throw Exception). Also wird ein Fehler gemeldet, wenn die DB versucht, in jene DataTable-Zelle NULL einzutragen. Aber Du kannst ja da auch z.B. (Null), (Empty) oder einen eigenen sinnvollen Default-Wert eintragen. Alles eine Frage der Einstellung ;)
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.