Announcement

Collapse
No announcement yet.

Probleme beim Updaten einer SQL-Server Datenbank

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Probleme beim Updaten einer SQL-Server Datenbank

    Hi, Ich weiß nicht, ob dies eher in den VB.NET Bereich gehört oder in den SQL-Server Bereich, aber da cross-postings nicht gehen, stelle ich das mal in eines, und hoffe dass man mir Bescheid gibt, sollte man es verschieben

    Also zum Problem:
    Beim Updaten einer Datenbank suche ich mir zunächst alle Datensätze, die einer bestimmten Bedingung entsprechen, Öffne dann einen SQLDataReader und gehe in einer Schleife Datensatz für Datensatz durch um entsprechende Felder zu setzen und eventuelle Fehler zu protokollieren, damit diese notfalls manuell nachgezogen weden können. Die Schleifendurchläufe zähle ich in einer Double (brauche ich für den Fortschrittsbalken in frm), die Felder setze ich durch einen DataWriter, der im Prinzip nichts anderes ist als eine Kapselung der Sammlung eines "UPDATE <Tabellenname> SET .. WHERE <DatensatzID>=..." Statements und dw.Update führt dann seinerseits sqlExecute für das Statement aus, der SqlDataReader wird von der Klasse clsdataReader gekapselt, die dann auch per Item(fldName) erhaltene Werte je nach Aufruffunktion in Strings, Doubles, Dates oder Integer umwandelt.

    [highlight=vbnet]
    ...
    Dim count As Integer
    Dim c as Double = 0.0
    count = session.db.sqlGetLng("SELECT Count(*) FROM KonfBezBedingungen" & session.db.WithNoLock & " WHERE NOT(Bedingung IS NULL)")
    If count > 0 And session.db.FieldType("KonfBezBedingungen", "Bedingung") = clsDatabase.DBFieldType.DBText Then
    frm.showinfo("Wandele KonfBezBedingungen...", 0)
    session.db.AddField("KonfBezBedingungen", "BackupLangtext", "MEMO")
    session.db.sqlExecute("UPDATE KonfBezBedingungen" & session.db.WithRowLock & " SET BackupLangtext=NULL")
    s = "UPDATE KonfBezBedingungen" & session.db.WithRowLock & " SET BackupLangtext=Bedingung WHERE NOT(Bedingung IS NULL)"
    session.db.sqlExecute(s)
    session.db.DelField("KonfBezBedingungen", "Bedingung")
    session.db.AddField("KonfBezBedingungen", "Bedingung", "TEXT(4000)")
    c = 0.0
    dr.OpenReadonly(session.db, "SELECT * FROM KonfBezBedingungen" & session.db.WithNoLock & " WHERE NOT(BackupLangtext IS NULL)")
    While dr.Read() And Not frm.Abbrechen
    Dim BedID As Integer = dr.getLng("KonfBezBedingungID")
    Try
    frm.showinfo("", c * 100.0 / CType(count, Double))
    dw.OpenEdit(session.db, "KonfBezBedingungen", "KonfBezBedingungID", BedID)
    s = dr.getStr("BackupLangtext")
    dw.SetFieldValue("Bedingung", s)
    dw.Update()
    Catch
    errlog.OpenLogFile("X:\Transfer\DietzM\NText2NVarc har.log")
    errlog.WriteLine(StrDup(80, "_"c), False)
    errlog.WriteLine("Für die KonfBezBedingung " & BedID & " konnte die Bedingung nicht übernommen werden. ", False)
    errlog.WriteLine(s, False)
    errlog.WriteLine(StrDup(80, "_"c), False)
    errlog.CloseLogFile()
    Finally
    If Not (dw Is Nothing) Then dw.Close()
    End Try
    c += 1.0
    End While
    dr.Close()
    session.db.DelField("KonfBezBedingungen", "BackupLangtext")
    End If
    ...
    [/highlight]

    Wenn ich diese Schleife aber im Debugger durchgehe, habe ich das Phänomen dass z.B. count =4084 ist, aber c=5217.0 oder aber (noch schlimmer) count ist 5547, c aber 5534.0, und es bleiben eine Menge unbearbeitete Datensätze zurück, was in diesem Fall fatal ist, da ich die Spalte danach im Glauben ich hätte alles korrekt zurückgeschrieben, entferne.

    Können diese Probleme irgendwie damit zusammenhängen, dass ich den eben gerade gelesenen Datensatz beschreibe, bevor ich zum nächsten gehe? Da ich aber das Feld in der WHERE-Klausel nicht anfasse, sollte es doch eigentlich nichts ausmachen. Oder liegt das Problem darin, dass ich das im Debug-Modus durchlaufe, und der SQLDataReader deshalb Blödsinn macht? Hat der SqlDataReader an sich irgendwelche Macken, die dieses Problem verursachen?

    Ich hoffe jemand kann mir helfen, ich habe nämlich keine Ahnung wo da der Wurm drinhängt. Gut, für das aktuelle Problem mag es möglich sein, die betroffenen Datensätze in eine andere Tabelle zu speichern, um den gleichzeitigen Zugriff auf denselben Datensatz zu vermeiden, wenn man sich aber so Szenarien ansieht, wie einen Abgleich aller Datensätze die als "frei" markiert sind, ob sie immer noch frei sind (was dann die Bedingung der Abfrage verändert) oder eine Iteration über alle Datensätze um z.B. Status-IDs umzusetzen, da kann es schon fatal sein, wenn man ein SQL-Statement wegen möglicher Probleme nicht nutzen kann, andererseits dem DataReader aber auch nicht trauen darf..

    Mit freundlichen Grüßen
    Martin Dietz

  • #2
    Hallo Martin,

    ich glaube wirklich, dass das zu ADO.NET gehört.

    Das Hauptproblem sehe ich in der Verwendung des DbDataReader. Dieser bietet nur ein Vorwärtslesen; die Anzahl der Datensätze ist also nicht bekannt. Der DbDataReader "blockiert" die aktuelle DbConnection. Wenn Du dann noch Änderungen dazwischen schiebst, bringst Du vermutlich alles durcheinander.

    Ich empfehle wirklich, das Standardverfahren: Alle benötigten Datensätze mit DbDataAdapter in ein DataSet/DataTable einlesen, dort Änderungen vornehmen, dann mit DbDataAdapter.Update die Änderungen zurückspeichern. Anleitung siehe openbook Einstieg VB 2008 Kap.8 (oder so) oder openbook VB 2005 Kap.25 ff.

    Jürgen

    Comment


    • #3
      Hmm, das jetzt im gesamten Projekt auf DbDataAdapter umzustellen wird zu aufwendig, vielleicht mach ich das dann im neuen Jahr, als Sofortlösung würde ich das also umstellen, indem ich eine extra Tabelle für das Backup nutze.

      Eine Blockierung der DbConnection allein kann es übrigens nicht sein, da sqlExecute für den UDATE- Befehl eine neue DbConnection aufmacht (sonst würde ja auch der Update-Befehl selbst gar nicht klappen), aber ich hoffe mal, was sich auch immer da gegenseitig in die Quere kommt, vermeide ich nun dadurch, dass der Schreib- und der Lesezugriff auf verschiedene Tabellen stattfindet.

      Erstmal danke, und falls ich mich nicht mehr melde Frohe Weihnachten!
      Martin Dietz

      Comment


      • #4
        Hallo Martin,

        Originally posted by M.Dietz View Post
        Hmm, das jetzt im gesamten Projekt auf DbDataAdapter umzustellen wird zu aufwendig,
        Vielleicht gibt es auch eine Methode, um das ganze Ergebnis des DbDataReader in eine DataTable zu übertragen. Leider finde ich diese gerade nicht; vielleicht findest Du es mit Suche nach "DataReader AND DataTable". *

        Dann hättest Du das Ergebnis des Einlesens ruck-zuck in einer DataTable, die erste DbConnection ist geschlossen, und Du kannst in Ruhe die Daten überarbeiten und zurückspeichern.

        Jürgen

        * Nachtrag: Nach längerer Suche habe ich nur folgenden (eigenen) Code gefunden:
        Code:
        OleDbCommand cmd = new OleDbCommand(strSql, conn);
        DataTable result = cmd.ExecuteQuery(CommandBehavior.CloseConnection);
        Der ist aber offensichtlich Blödsinn. Nun weiß ich nicht mehr weiter...
        Zuletzt editiert von Jürgen Thomas; 11.12.2008, 14:07.

        Comment


        • #5
          Originally posted by Jürgen Thomas View Post
          Der ist aber offensichtlich Blödsinn. Nun weiß ich nicht mehr weiter...
          Jetzt habe ich doch noch den "schnellen Weg" gefunden:
          [highlight=c#]OleDbCommand cmd = new OleDbCommand(strSql, conn);
          OleDbDataReader reader = cmd.ExecuteReader();
          DataTable table = new DataTable();
          table.Load(reader);[/highlight]
          Etwa drei Zeilen geändert, und Du kannst mit DataReader weiterarbeiten und hast an allen anderen Stellen die DataTable zur Verfügung!

          Jürgen

          1000 Beiträge erreicht - hoffentlich überwiegend hilfreiche.

          Comment


          • #6
            1000 Beiträge erreicht - hoffentlich überwiegend hilfreiche.
            Willommen im Club - gratuliere. Ja es waren fast alle hilfreich.
            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

            Comment

            Working...
            X